在Scala中,如果我想实现DSL,有没有办法执行以下操作:
我有一个名为"Draw"的对象,其中包含该函数 def draw(d:Drawable)
我怎样才能使它能够导入Object并在对象外部调用它,如:
draw ball
Run Code Online (Sandbox Code Playgroud)
如果球扩展了Drawable特征?问题是我想在一种中缀符号中使用draw,但我不想通过表示它实现类/对象来限定函数draw.
我是一名新的Scheme/Racket学生,所以请原谅任何明显的语法错误.
今天课堂上出现的方案列表'(a, b, c)应该是无效的,但是当我们运行它时,它返回:
>'(a . b . c)
(b a c)
Run Code Online (Sandbox Code Playgroud)
这毫无意义.Afaik,翻译应该创建一个带有'a和cdr'b'的cons单元格,'c应该是无效的.也就是说,翻译在这里做了一些非常奇怪的事情.这适用于#lang方案,#lang racket等.我们使用DrRacket作为翻译.
有趣的是,
>'(a . b . c . d)
Run Code Online (Sandbox Code Playgroud)
抛出异常并死亡.
我非常好奇,很想能够理解这一点,因为我不熟悉这门语言.谷歌非常无益(可能因为搜索条件有点含糊不清)谢谢!
编辑:可能是因为'(a . b . c)用b解释为中缀运算符.例如:>(4 . + . 6)返回10.也许解释器使用b像运算符?即,(b a c)像(+ 4 6)中缀一样.
实验说:
>(define b +)
>(define a 4)
>(define c 6)
>(a . b . c)
10
Run Code Online (Sandbox Code Playgroud)
所以我认为这解决了这个问题,但我仍然不完全理解"."的使用.在这种情况下运算符.我想我们已经解决了这个问题,但我们将非常感谢您的见解!
我喜欢常见的口齿不清,但有时输入简单的数学表达式是非常痛苦的
a(8b^2+1)+4bc(4b^2+1)
Run Code Online (Sandbox Code Playgroud)
(当然我可以转换它,但它有点慢,我先写(+()()),然后在每个括号中我放(*()())...)
我想知道这里是否有人知道更好的输入方法.我正在考虑编写一个数学宏,在哪里
(math “a(8b^2+1)+4bc(4b^2+1)”)
Run Code Online (Sandbox Code Playgroud)
扩展到
(+ (* a (1+ (* 8 b b))) (* 4 b c (1+ (* 4 b b))))
Run Code Online (Sandbox Code Playgroud)
但解析是名称很长的变量的问题.
有人有更好的建议吗?
给定中缀使用函数:
let f a b = (a+10, b)
f 4 5
=> (14,5)
4 `f` 5
=> (14,5)
Run Code Online (Sandbox Code Playgroud)
可以通过定义辅助函数来翻转参数:
let g = flip f
4 `g` 5
=> (15,4)
Run Code Online (Sandbox Code Playgroud)
内联是否可以这样做?
4 `flip f` 5
=> parse error on input `f'
4 `(flip f)` 5
=> parse error on input `('
Run Code Online (Sandbox Code Playgroud)
我的用例是Control.Arrow.first.代替
(+10) `first` (7,8)
(17,8)
Run Code Online (Sandbox Code Playgroud)
我更喜欢像我这样的前向应用程序式解决方案
(7,8) `forwardFirst` (+10)
Run Code Online (Sandbox Code Playgroud)
无需写
let forwardFirst = flip first
Run Code Online (Sandbox Code Playgroud) 让我们假设我们有一个LaTeX形式的表达式:
var latex =\frac{x}{\frac{y}{y}}
Run Code Online (Sandbox Code Playgroud)
所以需要的输出是:
output= (x)/((y)/(y));
Run Code Online (Sandbox Code Playgroud)
我尝试了一个示例,如链接中所述:将LaTeX转换为动态Javascript函数,但我得到上述乳胶的输出为:
(x)/(\frac{y){y}}`
Run Code Online (Sandbox Code Playgroud)
如何正确转换表达式?提前致谢!
编译器接受中缀+泛型方法,但使用它的语法是什么?例如,给出了两个相同的方法(模任意通用类型):
infix inline fun Int1.plus1(i: Int1) = Int1(this.value + i.value)
infix inline fun <U> Int1.plus2(i: Int1) = Int1(this.value + i.value)
Run Code Online (Sandbox Code Playgroud)
我可以写:
Int1(3).plus1(Int1(4))
Int1(3) plus1 Int1(4)
Int1(3).plus2<Int>(Int1(4))
Run Code Online (Sandbox Code Playgroud)
但这个电话无效:
Int1(3) plus2<Int> Int1(4)
Run Code Online (Sandbox Code Playgroud)
有人能解释我为什么吗?
根据 David MacQueen 在他对标准 ML报告1 的思考,
词法范围的中缀指令是 Pop-2 的一个不明智的遗产。它们使解析变得复杂并且它们不能很好地与模块系统一起工作,因为中缀指令不能通过结构导出或在签名中指定(并且添加这样的功能不是一个好主意)。
现在我确实同意他的说法,即infix[r]声明的私有范围是一个坏主意,它使导入的用户定义运算符变得毫无用处,但我为此设想的解决方案是实际导出签名中的这些声明..彻底摆脱它们。
在我所知道的具有固定性声明的语言(ML 和派生类、Haskell 和派生类、Prolog 等)中,我对它们是否记录了该想法的优点和/或缺点很感兴趣。更一般地说,语言实现者的既定设计经验可以为看起来(从用户角度)一个很好的便利功能的缺点带来有趣的见解。
所以我的问题是,简而言之,文献中是否有引用和/或已知问题支持 MacQueen 关于不输出固定性的观点?
我一直在考虑创建一种非常适合创建DSL的语言,允许定义中缀,后缀,前缀或甚至由多个单词组成的函数.例如,您可以按如下方式定义中缀乘法运算符(其中已定义了乘法(X,Y)):
a * b => multiply(a,b)
Run Code Online (Sandbox Code Playgroud)
或后缀"平方"运算符:
a squared => a * a
Run Code Online (Sandbox Code Playgroud)
或者是C或Java风格的三元运算符,它包含两个散布着变量的关键字:
a ? b : c => if a==true then b else c
Run Code Online (Sandbox Code Playgroud)
显然,在这种语言中存在大量的歧义空间,但如果它是静态类型的(使用类型推断),那么大多数歧义可以被消除,而剩下的那些可以被认为是语法错误(通过添加括号来纠正适当).
有什么理由我没有看到这会使这个极其困难,不可能,或者只是一个简单的坏主意?
编辑:很多人都指出了可以做到这一点或类似事情的语言,但我实际上对如何实现自己的解析器的指针感兴趣,或者如果这样做我可能会遇到的问题.
syntax parsing programming-languages infix-notation postfix-notation
换句话说,有没有一个很好的理由为什么不应该编译?
def f(xs: List[Int]) = xs.foldLeft(0) _ // OK
def f(xs: List[Int]) = (xs :\ 0) _ // OK
def f(xs: List[Int]) = (0 /: xs) _
<console>:15: error: missing arguments for method /: in trait TraversableOnce;
follow this method with `_' if you want to treat it as a partially applied function
Run Code Online (Sandbox Code Playgroud)
以下是一些解决方法:
def f(xs: List[Int]) = xs./:(0) _
def f(xs: List[Int]): ((Int, Int) => Int) => Int = (0 /: xs)
Run Code Online (Sandbox Code Playgroud)
但我的问题主要是关于一般的正确语法.
scala infix-notation currying partial-application associativity
假设我在R中有两个自定义中缀运算符:%foo%和%bar%.
我有两个运算符的表达式,例如:
x %foo% y %bar% z
Run Code Online (Sandbox Code Playgroud)
如何确定运算符的优先级%foo%和%bar%?
如何更改优先级,以便例如%bar%始终执行%foo%?在上面的例子中,这将是:
x %foo% (y %bar% z)
Run Code Online (Sandbox Code Playgroud) infix-notation ×10
haskell ×2
scala ×2
syntax ×2
common-lisp ×1
currying ×1
dsl ×1
expression ×1
generics ×1
kotlin ×1
latex ×1
list ×1
operators ×1
parsing ×1
prefix ×1
prolog ×1
r ×1
racket ×1
reader-macro ×1
s-expression ×1
scala-2.8 ×1
scheme ×1
sml ×1