分类: 软件

  • 🐢 深入浅出Common Lisp函数的奥秘

    在编程的海洋中,Common Lisp就像一只悠然自得的海龟,缓慢却坚定地游向知识的彼岸。在这篇文章中,我们将一起探索Common Lisp函数的定义、参数以及高阶函数等内容,确保每位读者都能在这片代码的海洋中畅游自如。

    ✍️ 定义新函数

    在Common Lisp中,定义一个新函数就像给你的程序添置一个新工具,它将帮助你完成特定的任务。使用defun宏来定义函数,其基本结构如同一个简洁的说明书:

    (defun name
      "一些说明文字"
      body-form*)

    举个例子,我们来定义一个简单的“Hello, World”函数:

    (defun hello-world ()
      "打印Hello, world"
      (format t "Hello, world"))

    在这个例子中,hello-world是函数名,()表示这个函数不需要参数,而(format t "Hello, world")则是函数体,它的使命就是向标准输出打印“Hello, world”。

    📦 函数形参列表

    形参列表就像是函数的邀请函,只有接受了这些邀请,函数才能顺利运行。在定义函数时,形参列表用于声明一些变量来接收传递给函数的实际参数。普通的形参列表要求每一个必要参数都必须提供实参,否则函数会婉拒执行。

    可选形参

    有时候,实参数可能少于形参数,这时可选形参就派上用场了。通过在必要形参后使用&optional,未赋值的形参可以用默认值填充。比如:

    (defun foo (a b &optional c d)
      (list a b c d))

    这个函数可以这样调用:

    (foo 1 2)    ; -> (1 2 NIL)
    (foo 1 2 3)  ; -> (1 2 3 NIL)
    (foo 1 2 3 4); -> (1 2 3 4)

    如果想为可选形参提供默认值,只需这样写:

    (defun foo (a b &optional (c 10))
      (list a b c))

    这样调用(foo 1 2)时,c会默认取值10。

    🌊 剩余形参

    当你需要传递多个参数时,剩余形参就能派上用场。通过在必要和可选形参后使用&rest,所有后续的实参将被收集到一个列表中。比如:

    (defun + (&rest numbers)
      ...)

    这意味着你可以传递任意数量的参数,函数会将它们整理成一个列表。

    🔑 关键字形参

    如果你只想为某些参数提供值,关键字形参将是一个完美的解决方案。在必要和可选形参之后,使用&key来定义关键字形参,比如:

    (defun foo (&key a b c)
      (list a b c))

    这样调用(foo :a 1 :b 2)时,它会返回(1 2 NIL),方便快捷。

    🌀 混合不同的形参类型

    在一个函数中,你可以灵活地混合不同类型的形参。常见的组合是必要形参和可选形参,或者是&optional&rest的组合。顺序上,必要形参应该放在前面,后续可以添加可选、剩余和关键字形参。使用关键字形参可以让你的代码更加易于维护和扩展。

    🔄 函数返回值

    在Common Lisp中,函数的返回值默认是最后一个表达式的值,也可以使用return-from语句在任何位置返回值。例如,下面的函数寻找一个数对,要求每个数都小于10,并且它们的乘积大于参数n

    (defun foo (n)
      (dotimes (i 10)
        (dotimes (j 10)
          (when (> (* i j) n)
            (return-from foo (list i j))))))

    🎭 作为数据的函数——高阶函数

    在Common Lisp中,函数不仅可以执行操作,还可以作为数据存储在变量中,甚至传递给其他函数。使用defun定义的函数实际上创建了一个新的函数对象并赋予其一个名字。你也可以使用lambda表达式创建匿名函数。例如:

    (funcall #'(lambda (x y) (+ x y)) 2 3)  ; 返回5

    🕵️‍♂️ 匿名函数

    使用lambda创建匿名函数的语法如下:

    (lambda (parameters) body)

    例如,创建一个匿名函数来增加两个数并调用它:

    (funcall #'(lambda (x y) (+ x y)) 2 3)  ; 返回5

    通过这些示例,我们可以看到Common Lisp的函数机制是多么强大与灵活。无论是定义函数、处理形参,还是使用高阶函数,Lisp都能让你如鱼得水,尽情地在编程的海洋里遨游。

    📚 参考文献

    • 编程之禅. (2021). Common Lisp函数. Retrieved from 编程之禅
  • Common Lisp:语法的迷宫与乐趣 🎭

    在编程的世界中,Common Lisp就像一位优雅的舞者,虽然动作复杂却充满魅力。今天,我们将一起走进这个迷宫般的语法世界,探索那些看似繁琐却又极具魅力的细节。准备好了吗?让我们开始这场冒险吧!

    📝 注释:编程的隐秘语言

    编程中的注释就像是旅途中那些小小的指示牌,它们指引着我们前行的方向。在Common Lisp中,注释的方式多种多样:

    • ;;;;:文件头注释,适合于介绍整个文件的背景。
    • ;;;:用于描述一大段代码的作用,像是为代码添加了一个精致的封面。
    • ;;:几行代码的功能性描述,注释与被注释的代码保持相同缩进,清晰明了。
    • ;:单行注释,简单直接,像是随手写下的便签。

    通过这些注释,程序员们能够在代码的海洋中保持清醒,不至于迷失方向。

    📜 S-表达式:编程的心脏

    S-表达式是Common Lisp的核心,它就像是一种神奇的魔法符咒。S-表达式的基本元素是列表(list)和原子(atom),其中列表由括号围绕,而原子则是不可分割的元素。比如:

    (1 2 3)
    ("stf" 1 2 3)
    (foo 1 2 3)
    (foo 1 2 3 (getMax 4 5))

    这些都是有效的S-表达式。可以想象,它们就像是不同口味的冰淇淋,组合后产生了无穷的可能性。

    🔢 常见原子类型:数字与字符串的舞蹈

    在Common Lisp中,常见的原子类型包括数字、字符串和名字。让我们来看看这些类型是如何配合演出的。

    数字的魅力

    数字的表示形式多种多样,既可以是简单的整数,也可以是复杂的浮点数。例如:

    123      ; 整数
    +122     ; 正数
    -122     ; 负数
    12.1     ; 默认精度浮点数
    121e-1   ; 科学计数法表示
    -5/4     ; 比值

    这些数字就像是一群舞者,各自展现着独特的风采。

    字符串的旋律

    字符串则由双引号包围的可见字符组成,反斜杠(\)作为转义字符,帮助我们在字符串中插入特殊字符。例如:

    “foo”      ; 表示由f,o,o组成的字符串
    “fo\o”     ; 同一个字符串

    字符串的魅力在于它们可以灵活地组合,形成动人的旋律。

    名字的身份

    在Common Lisp中,函数名和变量名是最常见的名字。几乎任何字符都可以出现在名字里,但有十个特殊字符需要注意:

    • 开括号 (
    • 闭括号 )
    • 双引号
    • 单引号
    • 反引号 `
    • 逗号 ,
    • 冒号 :
    • 分号 ;
    • 反斜杠 \
    • 竖线 |

    如果真要使用这些特殊字符,得加上转义字符哦。例如,on\off就可以作为一个名字。

    🚀 Lisp形式的S-表达式

    在Common Lisp中,函数调用和特殊操作符都是以S-表达式的形式出现的。让我们来看几个例子:

    函数调用

    函数调用的基本形式是:

    (function-name argument*)

    例如:

    (+ 1 2)            ; +号为函数名
    (/ 2 (+ 1 1))    ; 最外层的/是函数名,内部嵌套的+也为函数名

    这样的结构就像是一个层层叠叠的蛋糕,每一层都充满了惊喜。

    特殊操作符

    并非所有操作都能定义成函数,特殊操作符便是其中的一类。例如条件判断语句:

    (if (x) (format t “yes”) (format t “no”))

    这段代码就像是一个简单的问答游戏,返回“yes”或“no”,让我们感受到编程的乐趣。

    📦 宏:编程的魔法师

    在Common Lisp中,宏是一种特殊的功能,它以S-表达式为参数,返回一个Lisp形式。宏的求值过程包括两个阶段:首先将元素传递到宏函数,然后根据正常的求值规则进行处理。

    当Lisp代码被编译时,源文件中的所有宏形式将被递归展开,最终编译成一个FASL文件。这就像是一个魔法师,将复杂的咒语变为简单的指令。

    ⚖️ 真假与等价

    在Lisp中,符号NIL表示唯一的假值,而其他所有值都是真值T. ��NIL的特别之处在于,它既是原子又是列表,既可以作为假值使用,也可以作为空列表(())。

    等价判断

    Lisp提供了多种等价判断方式:

    • EQ:是最严格的等价判断,只有对象相同时返回T. ��
    • EQL:更宽松,当两个对象表示相同的字符或数字时,即使不是同一对象,也返回T. ��
    • EQUAL:在递归上具有相同结构和内容的列表被视为等价。
    • EQUALP:忽略大小写的字符串判断,只要表示相同数学意义的值,它们就是等价的。

    例如:

    (EQUALP “helloworld” “HelloWorld”) ; 返回T
    (EQUALP 1 1.0) ; 返回T

    这样的等价判断让我们在编程时更加灵活,仿佛拥有了多种视角。

    🎹 Emacs小技巧

    在使用Emacs进行Common Lisp编程时,有一些技巧可以帮助我们提高效率:

    • 选中代码后,使用 C-M-q 重新缩进整个表达式。
    • 在函数体的任何位置,通过 C-c M-q 来缩进整个函数体。

    这些小技巧就像是编程中的调味品,让我们的代码更加优雅。

    结语

    通过这次探索,我们不仅了解了Common Lisp的语法规则,还领略了其中的魅力与乐趣。编程不再只是冷冰冰的代码,而是充满了创意与表达的艺术。在这个迷人的世界中,愿你能找到属于自己的舞步,与Common Lisp共舞!


    参考文献

    • Common Lisp 语法规则 | 编程之禅. 访问链接: 编程之禅
人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 知差(chai)网
快取状态: No
内存使用量: 9.136 MB
资料库查询次数: 2
页面产生时间: 0.830 (秒)