我在列表上有一个基本问题
当我尝试使用cons运算符
创建List时,我收到以下错误scala> val someList = 1::2
<console>:10: error: value :: is not a member of Int
val someList = 1::2
^
但是如果你看下面的话,我一旦加上Nil就行了..
scala> val someList = 1::2::Nil
someList: List[Int] = List(1, 2)
我想知道为什么在我们创建列表时至少需要一次Nil
Nil是数据类型吗?还是空元素?
答案 0 :(得分:11)
正是因为这个原因。
value ::不是Int
的成员
在Scala中,运算符实际上是对象的函数。在这种情况下,::
是Nil
对象上的函数,实际上是一个空列表对象。
scala> Nil
res0: scala.collection.immutable.Nil.type = List()
当您执行1::2
时,Scala会在::
上查找名为2
的函数,但它找不到该函数。这就是它失败的原因。
注意:在Scala中,如果运算符的最后一个字符不是冒号,则在第一个操作数上调用运算符。例如,1 + 2
基本上是1.+(2)
。但是,如果最后一个字符是冒号,则在右侧操作数上调用该运算符。因此,在这种情况下,1 :: Nil
实际上是Nil.::(1)
。由于::
会返回另一个列表对象,因此您可以将其链接起来,就像1 :: 2 :: Nil
实际上是Nil.::(2).::(1)
一样。
答案 1 :(得分:7)
名称以:
结尾的中缀运算符被解释为右操作数上的方法调用。因此1 :: 2
为2.::(1)
,即它调用::
上的方法2
。同样,1 :: 2 :: Nil
为Nil.::(2).::(1)
。
第一个不起作用的原因是2
是Int
而Int
没有::
方法。第二个工作的原因是Nil
是一个列表,列表确实有::
方法。由于List.::
的结果也是一个列表,您仍然可以对第一个::
的结果调用::
。
答案 2 :(得分:2)
Nil
是将List
创建为递归数据结构的基本构建块。 List是有用的数据结构,它为头部(第一个元素)提供恒定的时间访问O(1)。
列出它的最小核心,建立在3个操作之上
head
,tail
和isEmpty
。 Nil
是List
的单例子类,因此它是一个特殊的类似实例,表示空列表。 缺点运算符::
在List上定义,通过在List中预先添加一个元素来递归地构建列表。
参见trait List
和object Nil
(高度简化)
trait List[A] {
def head: A
def tail: List[A]
def isEmpty: Boolean
}
case object Nil extends List[Nothing] {
def head = throw new NoSuchElementException("head of empty list")
def tail = throw new UnsupportedOperationException("tail of empty list")
def isEmpty = true
}
由于任何标识符/运算符以:
结尾,与右侧相关联,::
运算符也与右侧相关联。
当您编写1::2::3
时,scala会尝试将此调用重写为3.::(2.::(1))
。即3成为第一次调用::
的接收者,它不存在于任何任意数据类型(在这种情况下为Int)。
这就是为什么你在空列表上总是建立 - Nil。可以把它想象为在空列表Nil
上逐个添加每个元素。
答案 3 :(得分:1)
Scala中以冒号:
结尾的所有运算符都在右操作数上定义。
因此,当您撰写1::2
时,::
意味着应2
,Int
,Nil
,List
。{/ 1}
::
是1 :: 2 :: Nil
的值,并在其上定义了(Nil.::(2)).::(1)
的方法。因此,当您编写public class MyAccessDeniedHandler implements AccessDeniedHandler {
private AccessDeniedHandlerImpl accessDeniedHandlerImpl = new AccessDeniedHandlerImpl();
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
//Some CSRF related code
// Then call accessDeniedHandlerImpl.handle to handle request
accessDeniedHandlerImpl.handle(request, response, accessDeniedException);
}
/**
* The error page to use. Must begin with a "/" and is interpreted relative to the current context root.
*
* @param errorPage the dispatcher path to display
*
* @throws IllegalArgumentException if the argument doesn't comply with the above limitations
* @see AccessDeniedHandlerImpl#setErrorPage(String)
*/
public void setErrorPage(String errorPage) {
// You can set custom error page here
accessDeniedHandlerImpl.setErrorPage(errorPage);
}
}
时,它会被评估为render: function() {
var modalView =
<Button onPress={this.openModal3} style={styles.btn}>Position centered + backdrop + disable</Button>
<Modal style={[styles.modal, styles.modal3]} position={"center"} ref={"modal3"} isDisabled={this.state.isDisabled}>
<Text style={styles.text}>Modal centered</Text>
<Button onPress={this.toggleDisable} style={styles.btn}>Disable ({this.state.isDisabled ? "true" : "false"})</Button>
</Modal>
</View>
return (
<NavigatorIOS style ={{flex:1}}
ref={'nav'}
initialRoute={{
component: ()=> modalView,
title:'Photoos.Net',
passProps:{ name: this.props.title},
}}/>
);
}
});
。