我正在使用Parsec来解析一些表达式(有关更多上下文,请参阅此问题),我的代码中最相关的部分是:
statement :: Parser Stmt
statement = assignStmt <|> simpleStmt
assignStmt :: Parser Stmt
assignStmt =
do var <- identifier
reservedOp "="
expr <- expression
return $ Assign var expr
simpleStmt :: Parser Stmt
simpleStmt =
do expr <- expression
return $ Simple expr
Run Code Online (Sandbox Code Playgroud)
在行动:
boobla> foo = 100 + ~100
167
boobla> foo
解析器错误:(第1行,第4列):
意外结束输入需要
字母或数字或"="
第二个表达式应该评估为167,值foo.
我认为当Parsec尝试提取令牌时reservedOp "=",它应该失败,因为字符串中没有这样的令牌,那么就是尝试第二个函数simpleStmt并成功使用它.但它的工作方式不同:它期望更多的输入,只是抛出这个异常.
assignStmt如果字符串(或当前行)中没有其他字符,我应该使用什么来使失败.foo = 10应该解析,assignStmt并foo应该解析 …
我读过这个问题.这是被接受的答案的引用:
此实例已添加到基础4.3.xx中,它随ghc 7一起提供.同时,您可以
Either直接使用该实例,或者,如果您Either用于表示可能失败的内容,则应使用ErrorTmonad转换器.
我想Either用于这样的事情:
> (Left "bad thing happened") >>= \x -> Right (x ++ " ...")
Left "bad thing happened"
Run Code Online (Sandbox Code Playgroud)
因此,如果计算的一部分失败,Left则返回它.
实际问题是:我为什么要使用ErrorTmonad变压器而不是Eithermonad?我是Haskell的新手,我有点害怕monad转换器,特别是当我已经在其中编写代码时.
由Doug Hoyte阅读的书"Let Over Lambda",我发现了以下对#.符号的描述,即read-macro:
使用COMMON LISP内置的基本读取宏是#.读取时间eval宏.此读取宏允许您将对象嵌入到您读取的无法序列化的表单中,但可以使用一些lisp代码创建.
它来自第4章,本书的大部分内容可以在这里找到:http: //letoverlambda.com/index.cl/toc
这是本书中的示例,显示了每次都可以以不同的方式读取相同的表达式:
* '(football-game
(game-started-at
#.(get-internal-real-time))
(coin-flip
#.(if (zerop (random 2)) 'heads 'tails)))
(FOOTBALL-GAME
(GAME-STARTED-AT 187)
(COIN-FLIP HEADS))
* '(football-game
(game-started-at
#.(get-internal-real-time))
(coin-flip
#.(if (zerop (random 2)) 'heads 'tails)))
(FOOTBALL-GAME
(GAME-STARTED-AT 309)
(COIN-FLIP TAILS))
Run Code Online (Sandbox Code Playgroud)
接下来,作者演示了一些硬核技巧,用#宏创建变体.
因此,事实证明它#'也是某种读取宏,它通常在表示函数名称的符号之前使用.但这是否必要,他的工作到底是什么?
我可以在有#'或没有它的情况下为高阶函数添加符号:
CL-USER> (defun test nil t)
TEST
CL-USER> (funcall #'test)
T
CL-USER> (funcall 'test)
T
Run Code Online (Sandbox Code Playgroud)
取得同样的成功.
我正在为函数/宏组合编写一个宏(混合组合是可能的).在宏的内部,我必须处理代表函数的符号和不同地命名宏的符号.这是因为结果函数必须使用任意数量的参数(如果组合中的'最低'函数可以),并且我不能应用于apply宏.我的问题:如何确定给定符号代表什么:函数还是宏?
我需要重复列表的每个元素N次,即执行这种转换:
(1 2 3) => (1 1 1 2 2 2 3 3 3) ; N = 3
Run Code Online (Sandbox Code Playgroud)
保持元素的顺序很重要,即第一个元素应该重复N次,然后是第二个,等等.
到目前为止,这是我最好的尝试:
(defun my-fnc (lst &optional (n 2))
(mapcan (lambda (x) (make-list n :initial-element x))
lst))
Run Code Online (Sandbox Code Playgroud)
看起来很有效:
CL-USER> (defparameter *foo* '("foo" "bar"))
*FOO*
CL-USER> (setf *foo* (my-fnc *foo* 3))
("foo" "foo" "foo" "bar" "bar" "bar")
Run Code Online (Sandbox Code Playgroud)
......但不完全.问题是前三个元素是对同一个对象的引用.
("foo" "foo" "foo" "bar" "bar" "bar")
;{---------------} {---------------}
; the same string the same string
Run Code Online (Sandbox Code Playgroud)
这不是我想要的.
所以我的问题是:如何以大多数惯用的方式解决问题,以便结果列表的每个元素都可以引用复制的单独对象.
我需要使用Common Lisp读取文本文件.必须将文件读取到列表列表.列表中的每个列表必须包含文件中的一行.这该怎么做?我只做了这个:
(let ((in (open "D:/Others/rgr.txt")))
(format t "~a~%" (read-line in))
(close in))
Run Code Online (Sandbox Code Playgroud) 我在Lisp中不是很好,我需要做一个允许评估中缀表达式的函数.例如:(+ 2 3) -> (infixFunc 2 + 3).我尝试了一些变种,但都没有成功.
其中之一:
(defun calcPrefInf (a b c)
(funcall b a c))
Run Code Online (Sandbox Code Playgroud) 我得到一个八位字节(字节)和许多相关位,我想保留该给定字节的前n个(相关位)并将剩余的位设置为零.
例如
前4位相关的数字217将转换为208
0 0
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+ ==> +-+-+-+-+-+-+-+
1 1 0 1 1 0 0 1 1 1 0 1 0 0 0 0
Run Code Online (Sandbox Code Playgroud)
前8个(或更多)位相关的数字255根本不会改变
0 0
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+ ==> +-+-+-+-+-+-+-+
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Run Code Online (Sandbox Code Playgroud)
我写了这个函数来解决问题
(defun …Run Code Online (Sandbox Code Playgroud) 我试图声明一个局部变量在递归函数中使用,但我的let似乎每次函数recurses时调用.我希望let函数被调用一次来声明一个变量并给它赋值nil,然后我想在我的递归函数中更新这个局部变量的值而不用每个递归擦除它.
这是我的代码的简化框架.
(defun recursive-function (l1 l2)
(let ((?x nil))
(cond (...
...
... ;trying to update value of ?x here with (setf ?x 5)
(recursive-funtion (rest l1)(restl2)) ;recursive call made
))))
Run Code Online (Sandbox Code Playgroud) 我有C字符串保证是UTF-8编码.使用简单的字符串,我会这样做(假设我们可以使用pack和unpack):
result <- peekCString cstr
free cstr -- ? not really important here
return (T.pack result)
Run Code Online (Sandbox Code Playgroud)
并使用字符串:
withCString (T.unpack str) $ \cstr ->
use_string cstr
Run Code Online (Sandbox Code Playgroud)
这些功能的问题在于
它们将使用由当前区域设置确定的编码
...但我知道它总是应该是UTF-8,如果当前的语言环境指定不同的编码,我会得到错误的结果.
那么,我应该如何处理来回的编组Text?