我正在努力在Clojure中实现音乐编程语言解析器。这个想法是您使用文本文件作为命令行参数来运行解析器程序。文本文件包含我正在开发的这种音乐语言的代码;解析器解释代码并找出已经声明了哪些“乐器实例”,并且对于每个乐器实例,它解析代码并返回乐器所执行的一系列音乐“事件”(音符,和弦,休止符等)。 。因此,在最后一步之前,我们有多个“音乐代码”字符串,每个乐器实例一个字符串。
我对Clojure还是有些陌生,但仍在学习如何使用引用类型和线程/并发的细微差别。我的解析器将要进行一些复杂的解析,所以我认为使用并发来提高性能将使它受益。这是我的问题:
(map #(future (process-music-code %)) instrument-instances)
,但是我不确定是否有更好的方法来实现它,例如使用代理,通过Java interop进行手动线程或执行什么操作。我是并发编程的新手,所以以不同方式进行此操作的任何输入都很好。 最佳答案
我建议您通过过早的优化来分散自己对更重要的事情的注意力(例如弄清楚音乐语言的细节)。最好先编写最简单,最容易编写代码的解析器,以启动并运行它。如果发现它太慢,则可以查看如何优化以获得更好的性能。
解析器应该是完全独立的,并且无论如何可能不会花费很多代码,因此即使您以后将它扔掉并重写它,也不会造成很大的损失。如果编写第二个解析器,那么编写第一个解析器的经验将有所帮助。
其他要点:
您对引用类型绝对正确-您可能不需要任何引用类型。您的程序是一个编译器-它接受输入,对其进行转换,写入输出然后退出。这是纯函数式编程的理想情况,没有任何可变的东西,所有数据流都完全通过函数参数和返回值进行。
通常,使用解析器生成器是获得有效解析器的最快方法,但是我还没有找到Clojure真正好的解析器生成器。 Parsley有一个非常不错的API,但是它会生成LR(0)解析器,该解析器对于每个“节”的开头/结尾没有清晰,明确的标记的东西几乎是无用的。 (就像S表达式使用parens打开和关闭的方式一样。)那里有几个parser组合器库,例如squarepeg,但是我不喜欢它们的API,而是更喜欢使用以下代码编写自己的手动编码的递归下降解析器:我自己的解析器组合器之类的实现。 (它们的速度并不快,但是代码读起来确实不错。)
关于multithreading - 我应该如何使解析器并发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21148671/