我正在开发一种音乐编程语言,并使用JVM(通过Clojure)来播放用这种语言编写的乐谱.到目前为止,我们只是使用javax.sound.midi MidiSynthesizer来播放分数.
由于Clojure启动时间较慢,我们希望能够从命令行中获得分数并立即听到,我们选择将分数解释器构建为后台服务器进程,并使用更轻量级的方式与之通信用Java编写的命令行客户端.
所有这一切在大多数情况下都很有效,但是,有一个奇怪的问题,我们看到你在哪里启动服务器,然后关闭你的笔记本电脑*让它休眠,然后再打开它让服务器播放一个得分,音频不会立即发生,但会延迟几秒钟.使用调试日志记录运行服务器,我实际上可以看到MIDI音符开/关事件立即发生(并且正确定时),但音频被延迟.
*这可能是也可能不是特定于平台的.我在运行OS X 10.9.5 Mavericks的2014 Macbook Pro上看到了这个问题.
为了帮助缩小范围,我将这个简单的例子(使用Java,而不是Clojure)放在一起,演示了这个问题:
https://github.com/daveyarwood/java-midi-delayed-audio-example
我已经在这一段时间里摸不着头脑了.为什么音频会延迟,我们能做些什么呢?
我正在尝试为我正在编写的 Vim 插件编写语法规则,但在编写 Vim 正则表达式来匹配符号@后跟标识符时遇到问题,标识符定义为两个字母后跟任意数量的接受的人物。这是我到目前为止所拥有的:
syntax match aldaAtMarker "\v@[a-zA-Z]{2,}[\w[:digit:]\-+'()]*"
Run Code Online (Sandbox Code Playgroud)
我知道之后的所有内容都@有效(至少据我所知),因为我从aldaIdentifier似乎可以正常工作的规则中复制粘贴了它。但是,我在插入前面的文字符号时遇到了麻烦@,因为 Vim 正则表达式系统显然赋予了特殊含义@(see:help syntax和 grep for @)。
根据我上面写的语法规则,尝试加载插件会导致以下错误:
Error detected while processing /home/dave/.vim/bundle/vim-alda/syntax/alda.vim:
line 21:
E866: (NFA regexp) Misplaced @
Press ENTER or type command to continue
Error detected while processing /home/dave/.vim/bundle/vim-alda/syntax/alda.vim:
line 21:
E64: @ follows nothing
Press ENTER or type command to continue
Error detected while processing /home/dave/.vim/bundle/vim-alda/syntax/alda.vim:
line 21:
E475: Invalid argument: aldaAtMarker …Run Code Online (Sandbox Code Playgroud) 我正在阅读"Clojure的喜悦",以及关于paralellization,功能和部分的部分pvalues,pmap并pcalls简要介绍了如何使用每个部分.下面是给出的例子pvalues和pcalls:
(defn sleeper [s thing] (Thread/sleep (* 1000 s)) thing)
(pvalues
(sleeper 2 :1st)
(sleeper 3 :2nd)
(keyword "3rd"))
(pcalls
#(sleeper 2 :1st)
#(sleeper 3 :2nd)
#(keyword "3rd"))
Run Code Online (Sandbox Code Playgroud)
我理解两者之间的技术差异 - pvalues需要计算可变数量的"值",而pcalls并行地调用"任意数量的不带参数的函数".在这两种情况下,都会返回结果的延迟序列.
我的问题基本上是,你何时会使用一个与另一个?似乎唯一的语义差异是你#在每个参数之前粘贴一个pcalls,将它变成一个匿名函数.因此,纯粹从保存击键和使用更简单的代码的角度来看,使用它会不会更有意义pvalues?- 如果是这样,为什么甚至有pcalls功能?
我得到了pcalls,您可以替换一个引用函数的符号,但如果您想使用这样的函数pvalues,您可以将函数放在括号中,以便调用它.
我只是有点困惑,为什么Clojure有这两个相似的功能.有什么可以用一个而不是另一个吗?一些人为的例子可能会有所帮助.
parallel-processing multithreading clojure concurrent-programming
直到现在,我一直假设你可以在let绑定中做的任何事情,你都可以在defn表单的参数向量中做。
但是,我刚刚注意到这一点——如果我用let绑定来做到这一点,它会起作用:
(let [[x & more :as full-list] (range 10)]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; x: 0
; more: (1 2 3 4 5 6 7 8 9)
; full list: (0 1 2 3 4 5 6 7 8 9)
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试将其提取到函数中,则会出现异常:
(defn foo [x & more :as full-list]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; CompilerException java.lang.RuntimeException: Unexpected parameter, compiling:(/tmp/form-init615613631940782255.clj:1:1)
Run Code Online (Sandbox Code Playgroud)
值得注意的是,这有效:
(defn foo …Run Code Online (Sandbox Code Playgroud) 在Clojure中是否有一种简单/惯用的方法来测试给定序列是否包含在另一个序列中?就像是:
(subseq? [4 5 6] (range 10)) ;=> true
(subseq? [4 6 5] (range 10)) ;=> false
(subseq? "hound" "greyhound") ;=> true
Run Code Online (Sandbox Code Playgroud)
(subseq?理论上的功能在哪里可以做我所描述的)
似乎核心或其他Clojure库中没有这样的函数......假设这是真的,是否有一种相对简单的方法来实现这样的函数?
我一直在尝试将Clojure的协议扩展到已有的类型,但似乎每当我有一个问题时,"如何将此协议扩展到所有可用的集合?" 或者"我如何将此协议扩展到所有数字(长数,比率,整数,浮点数等)?" 我必须做很多谷歌搜索才能找到答案,即便如此,我也无法总能找到明确的答案.
任何人是否知道常用的实用参考的clojure.lang.Something,java.lang.SomeJavaClass等类和协议?我认为,如果我们有一些资源可以帮助像我这样几乎没有Java经验的Clojurians,那将是有益的.
编辑:在这段代码中,为了让您了解我在寻找什么:
(defprotocol X
(do-something [this]))
(extend-protocol X
?????? <--
(do-something [this] '(implementation goes here)))
Run Code Online (Sandbox Code Playgroud)
是否有一个资源可能有一个Clojure/Java类列表,它可能对扩展协议有用?
有没有办法在多方法中重用多个方法之间的解构?
(defmulti foo (fn [x] (:a x)))
(defmethod foo :1 [{:keys [a b c d e]}] (str a b c d e))
(defmethod foo :2 [a] "")
(defmethod foo :3 [a] "")
Run Code Online (Sandbox Code Playgroud)
现在这是一个简单的例子,但想象我们有一个更复杂的嵌套地图解构,我想在我所有defmethods的foo 上使用它.我该怎么办?
我不太喜欢在 Vim 中使用窗口(我更喜欢选项卡),但有些东西会使用它们,例如帮助文本缓冲区。我对此很满意,但由于我很少使用窗口,我通常需要一秒钟才能记住如何关闭窗口 ( <C-w>c) 并返回到我正在做的事情。所以我想在我的 vimrc 中添加一行来映射q以关闭窗口,前提是该窗口是帮助缓冲区。
我已经为 netrw windows 做了类似的事情,如下所示:
augroup wtf_netrw
autocmd!
autocmd filetype netrw nnoremap <buffer> q :e#<CR>
augroup END
Run Code Online (Sandbox Code Playgroud)
我尝试用以下方法做类似的事情filetype help:
:autocmd filetype help nnoremap <buffer> q <C-w>c
Run Code Online (Sandbox Code Playgroud)
但它不起作用——q在帮助文本缓冲区中输入只是执行默认q操作,记录宏。
当我尝试时:nnoremap q <C-w>c,输入q帮助文本缓冲区会按我的预期关闭窗口。
是否有一种特殊的方法来添加仅在帮助文本缓冲区中起作用的映射?
在Clojure中创建库时,最好在每个函数中包含docstrings和其他元数据,例如:
(defn ^Boolean foo
"Returns whether x is bar."
{:added "1.5"}
[x]
(bar? x))
Run Code Online (Sandbox Code Playgroud)
有时(使用高阶函数时)最终使用def (something-that-returns-a-fn)这样的函数更容易定义函数:
(defn wrapper [f]
"Some HOF, let's say it just prints 'WHARRGARBL' and then returns the fn."
(println "WHARRGARBL")
f)
(def foo
"Prints 'WHARRGARBL' and then returns whether x is bar."
(wrapper (fn [x] (bar? x))))
Run Code Online (Sandbox Code Playgroud)
如果我没有弄错的话,以这种方式定义函数会消除使用的优点defn- 即,文档字符串以一种很好的方式打印,而不是包括函数支持的arities,以及在函数定义中简洁地包含属性映射的能力.我是对的,还是有其他简洁的方法来记录通过HOF创建的功能?我可以这样做:
(defn foo
"Prints 'WHARRGARBL' and then returns whether x is bar."
{:added "1.5"}
[x]
((wrapper (fn [y] (bar? y))) x))
Run Code Online (Sandbox Code Playgroud)
但这似乎有点多余而且不必要地复杂,因为我将x的函数定义为y的函数,应用于x.有没有更好的办法?
我想生成5个不同的随机数.我已经生成了从0到100的范围.我想从该范围中随机选择5个数字.
我正在Clojure中实现一个音乐编程语言解析器.我们的想法是使用文本文件作为命令行参数运行解析器程序; 文本文件包含我正在开发的这种音乐语言的代码; 解析器解释代码并确定声明了什么"工具实例",并且对于每个工具实例,它解析代码并返回一系列音乐"事件"(音符,和弦,休止符等). .所以在最后一步之前,我们有多个"音乐代码"字符串,每个乐器实例一个字符串.
我对Clojure有点新,并且仍在学习如何使用引用类型和线程/并发的细微差别.我的解析器将进行一些复杂的解析,因此我认为使用并发来提高性能会受益.这是我的问题:
看来,最简单的方法是在初始解析(单线程操作)将文档"拆分"之后保存并发性,然后同时在不同的线程上解析每个工具的代码(而不是等到每个乐器完成解析,然后再移动到下一个).我是在正确的轨道上,还是有更有效和/或逻辑的方式来构建我的"并发计划"?
对于如何实现此并发解析,以及从性能或代码维护的角度来看,哪个可能最佳?看起来它可能很简单:(map #(future (process-music-code %)) instrument-instances)但是我不确定是否有更好的方法来执行它,例如使用代理,或通过Java互操作的手动线程,或者什么.我是并发编程的新手,所以不同方法的任何输入都会很棒.
从我所看到的,似乎Clojure的引用类型在并发编程中起着重要作用,我可以看到原因,但是在使用多个线程时是否总是需要使用它们?我是否应该担心我的一些数据是否可变?如果是这样,我正在编写的解析器的代码中应该是什么特别可变的?什么参考类型最适合我正在做的事情?我的程序工作方式的本质(用户以文本文件作为参数运行程序 - 程序处理它并将其转换为音频)使得看起来我不需要任何可变的东西,因为输入数据永远不会改变,所以我的直觉告诉我我不需要使用任何引用类型,但话说再说一遍,我可能不完全理解引用类型和Clojure中的并发性之间的关系.
multithreading clojure reference-type concurrent-programming