我最近在个人时间学习Scala.在工作中,我一直在学习C#/ .NET(4.0).我不是非常熟悉,要么能够最低限度地评估Lift或ASP-MVC 3.我正处于十字路口.鉴于我的时间非常有限,我必须在接下来的3-6个月内选择其中一个来学习和构建应用程序.
我今天遇到了这篇Lift文章,我立刻很感兴趣.我尝试过文章中概述的大部分内容,这让我感到无尽的沮丧和头痛.其中一些我最终放弃并实施原始的不安全的简单版本只是为了完成项目.因此,本文使Scala/Lift非常具有吸引力.
然后在午餐时,我的团队成员(和朋友)正在讨论他在.NET 4.0上使用C#进行ASP-MVC 3的工作.听起来学习和使用它会非常愉快.他谈到了足够多的东西,这些东西似乎与我早上读到的关于Lift的文章重叠.
我的问题是:鉴于我的时间有限,选择Scala/Lift而不是C#/ ASP-MVC 3有什么优点和/或缺点?与#Scala/Lift相比,C#/ ASP-MVC 3有哪些优势?
为了降低评估的复杂性:请假设每种技术的最新版本; Scala 2.8.1(2010/Dec),Lift 2.2(2011/Jan),C#/.NET 4.0(2010/Apr)和ASP-MVC 3(2011/Jan).
感谢您在这个关键架构决策点帮助我.
更新2011/Mar/19 12:25 CDT:
我曾经偶然发现了一些似乎对Scala/Lift方面非常有帮助的资源:
1.免费电子书(PDF和HTML),标题为"Exploring Lift(基于Scala) web-framework)"
2.由Lift的创建者发表的题为"View First"的 Wiki文章
电子书的第一章非常有用.我真的很喜欢Lift设计原则和实现的重点是"关注点分离"(将代码保留在显示片段之外)和"约定优于配置".
从我到目前为止看到的情况来看,虽然ASP-MVC 3使用了相同的"强大指南",但仍然依赖于代码和表示被"混合"的层.这是网站设计师和软件工程师在起源后都不敢踩的地方.IOW,在发起之后,有维护龙.我很想有人告诉我这里错了.
在将一些Java代码转换为Scala的过程中,我发现虽然Scala有一种contains方法Set,但是没有一种containsAll方法.我只是错过了正确的方法名称吗?
这是我编写的一些代码,以填补空白,以便我可以快速恢复工作.这还不够,还是我错过了一些微妙之处?
def containsAll[A](set: Set[A], subset: Set[A]): Boolean =
if (set.size >= subset.size)
subset.forall(a => set.contains(a))
else
false
Run Code Online (Sandbox Code Playgroud) 我刚看了一段Groovy发明家 James Strachan 的视频,他继续热爱Scala.这让我想要了解更多关于Groovy的信息,这些信息引导我使用Groovy ++.Groovy ++是Groovy的静态类型和编译版本(显然是完全动态的).
我试图弄清楚什么是Groovy ++(0.9.1的最新版本?)与Scala(2.10的最新版本)形成鲜明对比.在活动的Groovy ++论坛没有任何关于最新版本的这是能够吸引多少信息非常最近的活动.
那么,Scala与Groovy ++有一个很好的简单比较/对比吗?我对Groovy本身不感兴趣(除了作为Groovy ++设计的基础),因为我想并排比较静态编译的功能.一个简单的优点/缺点(即权衡)列表基本上是我所寻求的,而不必进行数十到数百小时的研究和实验.
提前感谢您提供有关此对比度和比较查询的任何信息.
当我正在设计模型时,我在两种不同的指示类型参数List必须的方法之间徘徊nonEmpty.我开始使用List[Int]附带的require声明来验证List是nonEmpty.
case class A(name: String, favoriteNumbers: List[Int]) {
require(favoriteNumbers.nonEmpty, "favoriteNumbers must not be empty")
}
Run Code Online (Sandbox Code Playgroud)
然后我需要使列表可选.如果List提供,它必须是nonEmpty.我正在使用Option[List[Int]]附带的require声明来验证,如果Option是nonEmpty,则列表也必须是nonEmpty.
case class B(name: String, favoriteNumbers: Option[List[Int]]) {
require(
favoriteNumbers.isEmpty || favoriateNumbers.get.nonEmpty
, "when defined, favoriteNumbers.get must be nonEmpty"
)
}
Run Code Online (Sandbox Code Playgroud)
但是,我需要List在我正在建模的系统中使用这个非空的.这意味着我的代码在require任何地方都有相同的语句重复.是否有一种(非ScalaZ)方式来获得一个新类型,比如说NeList,它定义并且行为与List相同,只有在NeList尝试实例化没有元素的情况下才会引发异常?
我试图谷歌为此而找不到一组搜索术语来磨练这个领域.我要么非常简单List,要么对ScalaZ的NEL(非空列表)进行各种引用.所以,如果有一个链接可以帮助解决这个问题,我很乐意看到它.
摘要:
从命令行(在Windows Server 2003 R2上),我键入:
> SET password=a^b
> ECHO %password%
Run Code Online (Sandbox Code Playgroud)
结果是"ab".怪胎插入符号(^)去了哪里?然后我尝试用^^,`^,%^,^^^"逃避"它,并且这些都没有使插入符号传递给echo命令.这个批处理文件位于中间.因此,我既不能更改源系统的密码以避免使用插入符,也不能将目标系统的密码更改为与源系统不同步.
细节:
我搜索了Google,然后搜索了SO.虽然我现在有很多关于如何更好地设计我的血腥Windows批处理文件的技巧,但问题仍然存在.
我有一个名为run.bat的批处理文件,它由一系列SET语句组成,用于设置运行Java命令行应用程序的上下文.在"cd"到正确的文件夹之后,在命令行上的提示符下(在Windows Server 2003 R2上),我输入:
> run the_name the_pass^word
Run Code Online (Sandbox Code Playgroud)
当我查看回显到命令行的输出时,我看到"java ... config.user_name = the_name config.password = the_password",其中...是一堆参数和库噪声与此问题无关.血腥的插入符号(^)消失了.
我已经尝试了各种逃避策略,我试图让插入符号显示出来.我无法找到任何会导致插入符号显示的内容...除了用引号包围密码,如我输入:
> run the_name "the_pass^word"
Run Code Online (Sandbox Code Playgroud)
...然后生成的命令行如下所示:
java...config.user_name=the_name config.password="the_pass^word"
Run Code Online (Sandbox Code Playgroud)
即我得到插入符号,但引号现在出现在字符串的内容中...这自然不适用于它们被传递的应用程序.
有没有人有一个明显的提示或技巧我错过了在命令行中输入的内容通过UNTOUCHED传递给我的内部利用?该值实际上是在%2的批处理文件变量中.但是,当我第一次看到%2的内容时,它已被"解除".
嗯,我不是Windows批处理文件的粉丝.
更新:
非常感谢Joshua McKinnon的回应.我选择了他作为答案,因为它解决了我的直接问题.但是,我想进一步阐述解决方案(是的,复数).
在批处理文件"run.bat"中,使用%~1语法,如下所示:
java MyClass username=%~1 password=%~2
Run Code Online (Sandbox Code Playgroud)
...然后在命令行输入:
> run mr_clean puke^^^^boy
Run Code Online (Sandbox Code Playgroud)
要么
> run mr_clean "puke^^boy"
Run Code Online (Sandbox Code Playgroud)
然后,这将导致最终执行的语句看起来像:
java MyClass username=mr_clean password=puke^boy
Run Code Online (Sandbox Code Playgroud)
希望这有助于其他节省时间.我结束了6个小时的切线试图追捕这种特质(更像是白痴同步).
六年前,我烧了几天试图追捕我完全确定的框架随机响应的地方.在精心追逐整个框架确保它全部使用相同的Random实例后,我继续追逐单步执行代码.这是高度重复的迭代自调用代码.更糟糕的是,该死的效果只会在完成大量迭代后出现.在+6小时之后,当我在javadoc中为HashSet.iterator()发现一行时,我终于处于智慧状态,表明它不能保证返回元素的顺序.然后我浏览了整个代码库,并用LinkedHashSet替换了所有HashSet实例.而且,我的框架正好向确定性生活迈进!哎呀!
我现在刚刚经历过同样的FREAKIN影响(至少这次只有3个小时).无论出于何种原因,我都错过了HashMap碰巧为其keySet()获得相同方式的细节.
这是关于这个主题的SO线程,虽然讨论从来没有完全回答我的问题:HashSet的迭代顺序
所以,我很好奇为什么会这样.鉴于我两次都有一个庞大的单线程java应用程序在完全相同的实例化/插入空间中使用完全相同的JVM参数(来自同一批处理文件的多次运行)在同一台计算机上运行,几乎没有其他任何运行,这可能会扰乱JVM使得HashSet和HashMap在经过大量迭代之后会表现得不可预测(并不是因为javadoc说不依赖于顺序而不一致)?
从源代码(java.util中的这些类的实现)或者你对JVM的了解(可能是某些GC影响内部java类在分配内部存储空间时获得非零内存的位置)的任何想法?
在下面的代码中,我需要从toSearch中获取元素,任何元素.我无法在Set接口定义中找到有用的方法来返回该集合的单个(随机,但不是必需的随机)成员.所以,我使用了toArray()[0]技术(见下面的代码).
private Set<Coordinate> floodFill(Value value, Coordinate coordinateStart)
{
Set<Coordinate> result = new LinkedHashSet<Coordinate>();
Set<Coordinate> toSearch = new LinkedHashSet<Coordinate>();
toSearch.add(coordinateStart);
while (toSearch.size() > 0)
{
Coordinate coordinate = (Coordinate)toSearch.toArray()[0];
result.add(coordinate);
toSearch.remove(coordinate);
for (Coordinate coordinateAdjacent: getAdjacentCoordinates(coordinate))
{
if (this.query.getCoordinateValue(coordinateAdjacent) == value)
{
if (!result.contains(coordinateAdjacent))
{
toSearch.add(coordinateAdjacent);
}
}
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我所讨论的另一种技术是用" toSearch.iterator().next() " 替换" (Coordinate)toSearch.toArray()[0] ".哪种技术toArray()或iterator()最有可能以最少的GC(垃圾收集)影响执行最快?
我的直觉(在编写这个问题之后)是使用迭代器的第二种技术将更快地执行并且降低GC的开销.鉴于我不知道传递的Set的实现(最可能假设HashSet或LinkedHashSet),每个toArray()或iterator()方法会产生多少开销?任何有关这方面的见解将不胜感激.
问题(从上面重复):
对此的上下文非常简单.我的假设是基于Odersky的书"Scala编程,第2版",第8.5节描述"占位符语法".
我有一个List [List [Boolean]](即一个矩形位图),我试图计算值"true"的总出现次数.这是定义执行正常的数据的REPL行:
val rowsByColumns =
List( List(false, true, false)
, List(true, true, true)
, List(false, true, false)
)
Run Code Online (Sandbox Code Playgroud)
接下来,我尝试使用以下行计算"true"的出现次数.而不是执行,我收到一个错误:
val marks = (for(row <- rowsByColumns)
yield {row.foldLeft[Int](0)(_ + (if (_) 1 else 0))}).sum
<console>:8: error: wrong number of parameters; expected = 2
val marks = (for(row <- rowsByColumns) yield {row.foldLeft[Int](0)(_ + (i
f (_) 1 else 0))}).sum
^
Run Code Online (Sandbox Code Playgroud)
我不理解错误,因为我有两个下划线代表函数的参数.所以,我通过写这个执行得很好的函数使函数更加明确:
val marks = (for(row <- rowsByColumns)
yield {row.foldLeft[Int](0)((sum, marked) => sum + (if (marked) 1 else 0))}
).sum
Run Code Online (Sandbox Code Playgroud)
我的问题是这样的:为什么我收到错误并且不太明确的情况,但是当我通过减少"简化"来映射函数时,它是否正确执行? …
我很难弄清楚如何从Scala高阶函数定义跳转到提供的示例.在幻灯片81上的幻灯片放映中提供了它.
这是高阶函数定义:
trait X[A] { def map[B](f: A => B): X[B] }
Run Code Online (Sandbox Code Playgroud)
这是提供的示例:
(1 to 10) map { x => x * 2 } // evaluates to Vector(2, 4, ..., 20)
(1 to 10) map { _ * 2 } // shorthand!
Run Code Online (Sandbox Code Playgroud)
咦?我不知道在这里有一些步骤.我得到的例子可能是利用函数定义和一些Scala细节.我只是没有足够的经验阅读Scala并做出连接假设.
我的背景是Java OO.我现在正在学习Scala和函数式编程.这不是第一个我不明白的例子.这只是第一个我觉得我有勇气发帖知道我会看起来无知的人.
我确实试过研究这个.首先,我去了Scala"圣经","Scala第二版编程",并尝试从那里了解是否存在(第165-9页).然后,我在StackOverflow上搜索了一下.我找到了几个围绕该地区的链接.但是,实际上并没有向我展示Scala高阶函数定义与提供的示例之间的连接,其方式是映射到此幻灯片中的特定实例.
这是我在StackOverflow上发现的:
我刚才意识到我跳过谷歌直接进入StackOverflow.嗯.如果你google并找到正确的链接,我很乐意看到它.我没有时间筛选使用像Monkey-monad,blastomorphisms等术语的所有谷歌链接,同时让我更加困惑,不太可能尝试解决这个问题.