我正在尝试深入研究clojure和函数式编程.
在我的代码的某些时候,我有一个(def server (spawn-server))
.现在我想要一个REPL的短函数来检查这个套接字的状态.
这就是我现在所拥有的:
(defn status []
(if server
(
(println "server is up and running")
(println "connections:" (connection-count server))
)
(println "server is down")))
Run Code Online (Sandbox Code Playgroud)
如果服务器是nil,一切正常,但如果服务器正在运行,这是REPL上的输出:
=> (status)
server is up and running
connections: 0
#<CompilerException java.lang.NullPointerException (NO_SOURCE_FILE:0)>
Run Code Online (Sandbox Code Playgroud)
我不确定我是否看到了问题,但我无法弄清楚这应该如何工作:-)我在这里有这样的:
((println "foo")(println "foo"))
Run Code Online (Sandbox Code Playgroud)
哪个会被评估到(nil nil)
NullPointerException的结果?
通常我不会使用外括号,但如何为if条件创建某种"块"语句.如果我不使用它们,第二个println将被用作其他.
什么是有效的是使用let作为某种"块" - 陈述:
(let []
(println "server is up and running"),
(println "connections:" (connection-count server)) )
Run Code Online (Sandbox Code Playgroud)
但我不确定这是否是"正确"的解决方案?
您发现自己使用哪些鲜为人知但有用的Clojure功能?随意分享小技巧和习语,但试着限制你自己的核心和贡献.
我在这些类似问题的答案中找到了一些非常有趣的信息:
对于其他语言,还有更多的"隐藏功能"问题,所以我认为为Clojure设置一个也很好.
一些文献说"以下形式的第一个子形式......"或"评估形式......",而其他一些文献说"评估表达......",大多数文献似乎都使用这两个术语.这两个术语是否可以互换?意义上有区别吗?
我有一个小的替代实现groupBy
,这对我来说比版本更有用Data.List
,因为它不要求测试是等价关系:
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' f = foldr step []
where step x [] = [[x]]
step x (xs:xss)
| x `f` head xs = (x:xs):xss
| otherwise = [x]:xs:xss
Run Code Online (Sandbox Code Playgroud)
然而,它太急切,不会开始计算输入,如groupBy' (<) [1,2,3,2,3,4,1,undefined]
.我已经阅读了HaskellWiki和Wikibooks的文章,这些文章解释了为什么某些事情,比如模式匹配,可以使函数不那么懒惰,我想我理解那里给出的大多数例子.不过,我不明白为什么这个功能无法开始产生输出,直到它击中undefined
.模式是否匹配导致此行为?
由于我刚读过这些文章,可能缺乏经验使我无法将我在那里阅读的内容应用到我的示例代码中.那么,为了表现得更懒,这个特定的实现怎么能改变呢?
对于一个Lisp类,我们给了一个简单的行转置密码作业,我试图在Haskell中解决它.基本上,只需将字符串拆分为长度行n
,然后转换结果.生成的字符列表列表的串联是加密字符串.解码有点困难,因为输入的最后一行可能缺少元素(结果中的列不完整),这些元素必须要处理.
这是我在Haskell中的解决方案:
import Data.List
import Data.Ratio
import Data.List.Split
encode :: String -> Int -> String
encode s n = concat . transpose $ chunk n s
decode :: String -> Int -> String
decode s n = take len $ encode s' rows
where s' = foldr (insertAt " ") s idxs
rows = ceiling (len % n)
idxs = take (n-filled) [n*rows-1,(n-1)*rows-1..]
filled = len - n * (rows - 1)
len = length s
insertAt :: …
Run Code Online (Sandbox Code Playgroud) 我有一个问题,如何返回没有给定列表的第n个元素的列表?例如,给定列表:(1 2 3 2 4 6)
和给定n = 4
,在这种情况下,返回列表应该是(1 2 3 4 6)
.
我正在开始学习clojure,其中很多部分都是使用库和依赖...我使用了javascript和ruby,他们有rubygems和npm ..非常简单......现在我正在尝试使用leiningen ..我已经安装了这个,我使用emacs并安装了elein ...我可以创建一个项目,处理库和依赖项并且工作正常..但我不能使用repl和我的粘液"评估表达式并评估地区"不工作......我真的是新手与粘液和clojure模式......和leiningen的更多新手,我不知道工作流程是怎样的...
我将我的库设置在项目中,我的主命名空间并调用"elein-deps"或"elein-install"
我编写了我的代码并使用"elein-run"运行它......运行正常
但我如何使用repl ..有一个自动加载leiningen repl的方式或者我需要在我的repl中导入我的文件和命名空间(对不起但我是clojure的新手,我不习惯加载方式使用它的文件和命名空间...我必须使用"load-file"和我文件的完整路径......或者我必须使用"use"??)
如果可以解释我如何与leiningen在clojure内的工作流程我会很感激..非常感谢!!
我试图在APL的布尔向量中找到最长的1个连续链的长度.在Haskell中,如果我有一个由1和0表示的布尔列表,我可以这样做:
Prelude> scanl (\acc x -> x*(acc+1)) 0 [0,0,1,1,0,1,1,1,1,0,1]
[0,0,0,1,2,0,1,2,3,4,0,1]
Run Code Online (Sandbox Code Playgroud)
然后取一个最大值.
我试图在APL做类似的事情:
{?×?+1}\0 0 1 1 0 1 1 1 1 0 1
0 0 1 2 0 4 8 16 32 0 64
Run Code Online (Sandbox Code Playgroud)
这根本不是我期望的向量.我曾假设⍺会在扫描/缩小的上下文中引用累加器,而⍵会引用向量的下一个元素,但我的理解似乎有点过时了.这些简单的例子让我感到困惑:
{?}\1 1 1 1 1
1 1 1 1 1
{?+?}\1 1 1 1 1
1 2 4 8 16
{?×?}\1 1 1 1 1
1 1 1 1 1
Run Code Online (Sandbox Code Playgroud)
是否有可能(在实践中)在APL中使用用户定义的函数和扫描/缩小?如果是这样,它是如何工作的,⍺和what指的是什么?
我有一个字典,"得分",整数,我想找到最高价值的关键字.我用过这段代码:
key = max(scores, key=scores.get)
Run Code Online (Sandbox Code Playgroud)
但是,这只会给一把钥匙.这如何处理最高价值的关系?我只收到一个号码.在领带的情况下是哪一个?如何获得最高价值的所有密钥?谢谢你的帮助.
我是Common Lisp的新手,正在尝试repeatedly
从Clojure 实现a 。例如
(repeatedly 5 #(rand-int 11))
Run Code Online (Sandbox Code Playgroud)
这将收集5个(rand-int 11)调用,并返回一个列表:
(10 1 3 0 2)
目前,这是我正在做的:
(defun repeatedly (n f args)
(loop for x from 1 to n
collect (apply f args)))
Run Code Online (Sandbox Code Playgroud)
看起来不太好,我必须这样称呼:(repeatedly 5 #'random '(11))
。有没有办法像Clojure的语法那样使函数更直观?
代码可能会变得很丑陋:(repeatedly 5 #'function (list (- x 1)))
。
对于一个赋值,我们必须实现像一个非常基本的sexp解析器,这样的输入,如:
"((a b) ((c d) e) f)"
Run Code Online (Sandbox Code Playgroud)
它将返回:
[["a", "b"], [["c", "d"], "e"], "f"]
Run Code Online (Sandbox Code Playgroud)
由于这是一个更大的赋值的一部分,解析器只给出有效的输入(匹配的parens和c).我在Ruby中提出了以下解决方案:
def parse s, start, stop
tokens = s.scan(/#{Regexp.escape(start)}|#{Regexp.escape(stop)}|\w+/)
stack = [[]]
tokens.each do |tok|
case tok
when start
stack << []
when stop
stack[-2] << stack.pop
else
stack[-1] << tok
end
end
return stack[-1][-1]
end
Run Code Online (Sandbox Code Playgroud)
这可能不是最好的解决方案,但它可以完成这项工作.
现在,我对一个惯用的Haskell解决方案的核心功能感兴趣(即我不关心lexing或选择分隔符,考虑已经lexed输入会很好),如果可能只使用"核心"haskell,没有扩展或者像parsec这样的库.
请注意,这不是赋值的一部分,我只是对Haskell的处理方式感兴趣.
我有以下数学表达式:
; f(n) = f(n - 1) + f(n - 2) where n >= 2
; f(n) = n where n < 2`
Run Code Online (Sandbox Code Playgroud)
我将其转换为正常的递归LISP调用:
(define (f n)
(cond ((< n 2) n)
(else (+ (f (- n 1))
(f (- n 2))))))
Run Code Online (Sandbox Code Playgroud)
我如何将上述内容转换为尾递归过程?我不习惯函数式编程,所以我有点挣扎.
为什么(defun boolimplies (a b) (or (not a) b))
如果称为
(boolimplies 'a 'b)
返回B
?
即使我不使用任何布尔值(NIL,T)而只是变量名,它如何得出这个结论?