宏 - >具有匿名功能

时间:2012-05-24 15:10:40

标签: clojure

我理解宏 - >在clojure中应用了给出的参数所提供的所有函数。但是,它似乎不适用于匿名函数(在clojure 1.3.0上)。例如:

user> (-> 4 inc inc dec)
5

可是:

user> (-> 4 #(+ % 1) #(- % 1) #(+ % 1))

返回错误:

clojure.lang.Symbol cannot be cast to clojure.lang.IPersistentVector
[Thrown class java.lang.ClassCastException]

如果有人知道解决方法会有所帮助。谢谢!

3 个答案:

答案 0 :(得分:38)

您可以在Clojure宏中使用匿名函数。你遇到了问题,因为你遗漏了一些括号。 :)您的示例在下面编辑。

(-> 4 (#(+ % 1)) (#(- % 1)) (#(+ % 1)))

答案 1 :(得分:27)

(这是基于我在评论中发布的问题的answer。)

->宏获取每个参数,必要时将其作为列表(将“原始”函数应用于无参数 - 将myfunc转换为(myfunc)),然后插入第一个参数将->作为每个列表中的第二个参数。

所以(-> foo myfunc)变为(-> foo (myfunc)),大致为(myfunc foo)

这一点在docs for ->

中有所描述

匿名函数的问题在于它们是由读者宏生成的described here (scroll down)。这意味着#(...)被转换(正常的宏扩展之前)到(fn [...] ...)。这很好,但是,关键的是,已经是一个列表

所以宏认为匿名函数已经被应用,实际上它正在遇到一个函数定义(两个都是列表)。并添加“额外”的parens - 如上面在另一个答案中所述 - 将匿名函数应用于no args。

这种不直观的行为的原因是->宏使用的dwim(do-what-what-mean-mean,not dwim-witted,尽管...)启发式,添加到允许你通过将它们包含在列表中来提供“裸”功能而不是要求你将它们应用于没有args,只是一个启发式 - 它只是测试一个列表 - 并且被创建的函数定义混淆了读者宏。

[我的脾气暴躁,->实施得很差,应该拒绝所有“裸”功能,而只是接受功能应用;然后它会显得更加一致。如果没有,那么至少文档可以更清楚,解释将事物放在列表中的激励语义。]

答案 2 :(得分:2)

您的具体案例可以通过以下方式解决:

Private Sub Workbook_BeforeClose(Cancel As Boolean)

  If ActiveWorkbook.Saved = True Then
     Cancel = False
  Else

     Dim iReply As Byte, iType As Integer

     Dim events As Boolean
     Dim alerts As Boolean

     events = Application.EnableEvents
     alerts = Application.DisplayAlerts

     Application.EnableEvents = False
     Application.DisplayAlerts = False

  StartQuestion:

     ' Define buttons argument.
     iType = vbYesNo + vbQuestion + vbDefaultButton2
     iReply = MsgBox("Would you like to save now?", iType)

     Select Case iReply
       Case Is = vbYes         ' user chose Yes save current workbook

         'The following statements shows the save as dialog box with default path
         Set FileSaveName = Application.FileDialog(msoFileDialogSaveAs)

         FileSaveName.InitialFileName = ThisWorkbook.Name
         FileSaveName.FilterIndex = 2   'select to save with a ".xlsm" extension
         FileSaveName.Title = "Save As ... "

         intchoice = FileSaveName.Show

         If intchoice = 0 Then
         Else
            FileSaveName.Execute
         End If

         If ActiveWorkbook.Saved = True Then
            ActiveWorkbook.Close
            Cancel = False
         Else
            GoTo StartQuestion
         End If

      Case Is = vbNo           ' user chose No, don't save

        ActiveWorkbook.Saved = True
        ActiveWorkbook.Close
        Cancel = False

     End Select

     Application.EnableEvents = events
     Application.DisplayAlerts = alerts

   End If

End Sub

其中线程第一个宏(-> 4 (+ 1) (- 1) (+ 1)) 负责将上一步的结果作为第一个参数插入" current"功能

混淆起因于->不是一个函数而是一个宏,并且在这种情况下对参数的处理方式非常不同,如其他答案所解释的那样。