首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

clojure规范fdef不起作用-传递递归定义时

在Clojure中,fdef是用于定义函数规范的宏。它可以用来指定函数的输入和输出的约束条件,以及其他的属性。然而,在传递递归定义时,fdef可能会失效。

传递递归定义是指函数在其定义中调用自身的情况。在这种情况下,fdef可能无法正确地应用于递归调用的函数。

这是因为fdef是静态的,它只能应用于函数的顶层定义,而无法适用于递归调用中的函数。当函数在递归调用中调用自身时,fdef无法捕获到这些调用,因此无法对其进行约束。

解决这个问题的一种方法是使用clojure.spec库。clojure.spec是Clojure的一个核心库,用于定义和验证数据的规范。通过使用clojure.spec,可以在递归调用中对函数进行规范。

首先,需要使用clojure.spec定义函数的规范。然后,在递归调用中,可以使用s/valid?函数来验证函数的参数是否符合规范。

以下是一个示例:

代码语言:clojure
复制
(require '[clojure.spec :as s])

(s/def ::my-arg integer?)
(s/def ::my-return integer?)

(defn my-fn [x]
  (if (zero? x)
    0
    (inc (my-fn (dec x)))))

(s/fdef my-fn
  :args (s/cat :x ::my-arg)
  :ret ::my-return)

(s/valid? ::my-arg 5) ; true
(s/valid? ::my-return 10) ; true
(s/valid? (s/fspec :args ::my-arg :ret ::my-return) my-fn) ; true

在上面的示例中,我们使用了clojure.spec来定义了函数my-fn的参数和返回值的规范。然后,我们使用s/valid?函数来验证规范是否生效。

需要注意的是,虽然clojure.spec可以在递归调用中对函数进行规范,但它并不会自动地对递归调用进行验证。因此,在递归调用中,仍然需要手动使用s/valid?函数来验证参数是否符合规范。

推荐的腾讯云相关产品和产品介绍链接地址:

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Clojure与LispClojure与Lisp

但是,历史上也有对lisp进行诋毁的人,或许称为抱怨更为合适. lisp发展过程中,没有完整的规范, 各种不兼容的实现,陈旧落伍的限制.cruft accumulate 在其存在的四五十年里一直存在....可是,IBM旗下的Fortran表处理语言却未能支援符号运算的递归、条件表达式、动态存储分配及隐式回收等功能。...它有自己的字面表示形式(literal representation),能够储存在变量中,也能当作参数传递。一种数据类型应该有的功能,它都有。 3 递归 Lisp是第一种支持递归函数的高级语言。...事实上,Lisp语言就是这样定义的,John McCarthy把语言设计成这个样子,就是为了让这种推导成为可能。 Clojure简介 运行于Java虚拟机的List方言Clojure....Clojure 是一种函数式编程语言 它囊括了函数式编程的所有精华: 避免了不稳定状态、递归、更高阶的函数等。

1.9K30

我是怎样学习新编程语言的

这种胜任力错觉导致最常见的后果是以为掌握了某种技能,真正开始解决问题,要么是半天摸不着头绪,要么就是处处掣肘。...Clojure中有keyword,如{:name "clojure"},而Python中并没有这样的数据类型,我只好使用{'name': "python"},那么Elixir呢?...defp tree_format(parent_dir, dir_name) do %{:name => dir_name, :children => []} end end defp定义了一个私有的方法...和Clojure(绝大数Lisp)中的(cons dir_name children)类似。 操作符|除了可以前置列表元素,递归解构也是一把好手。 defp decorate(is_last?...在添加前缀的步骤[prefix_first parent...]中,经验里字符串的拼接常用符号+不起作用了,换成了,这个是靠试错得出来的。

93130
  • 函数式编程那些事儿

    Clojure,Common Lisp,Erlang,Haskell和Scala是遵循函数式编程方法的一些著名编程语言。...使用函数式编程风格编写代码,有能力的编译器将能够: 记住结果 并行运算 等待评估结果 递归 在函数式编程范例中,没有for和while循环。相反,函数式编程语言依赖于递归进行迭代。...递归是使用递归函数实现的,递归函数会重复调用自己,直到达到基本情况为止。 引用透明性 一旦在函数式编程语言中定义了变量,就不允许在程序执行期间更改它们持有的值。这称为引用透明性。...为了在使用功能编程开发的程序中存储其他值,必须定义新变量。在这样的程序中,变量的状态在任何时候都是恒定的。...它的样式将函数视为值,并将其作为参数传递给其他函数。它增强了代码的理解性和可读性。

    86540

    实用的函数式编程

    所有的 map, reduce 和递归 -- 尤其是 尾递归 , 都非常简单. 使用这些只是一个熟悉程度的问题. 一旦你熟悉这些概念以后 -- 并不会花费太长时间, 编程会变得容易的多....我最喜欢的是 Clojure. 因为 Clojure 极其简单. 它是 Lisp 的一个方言, Lisp 是一个十分简单和漂亮的语言....当你想要对一个对象进行改变, 得到一个新的对象就好了, 之前的对象无须改变. 一旦你习惯于此, 这是十分容易处理的. 再回到面向对象....最好是用例子解释一下: (defprotocol Gateway (get-internal-episodes [this]) (get-public-episodes [this])) 上面的代码定义了一个...在上例中,接口的实现只是通过传递 db 简单地委托给了一些本地函数。

    1.1K20

    Clojure 运行原理之编译器剖析

    Compiler.java Compiler 类主要有三个入口函数: compile,当调用clojure.core/compile使用 load,当调用clojure.core/require、clojure.core.../use使用 eval,当调用clojure.core/eval使用 这三个入口函数都会依次调用 macroexpand、analyze 方法,生成Expr对象,compile 函数还会额外调用...macroexpand Macro 毫无疑问是 Lisp 中的屠龙刀,可以在编译自动生成代码: static Object macroexpand(Object form) { Object...根据 JVM bytecode 的规范,每个.class文件都必须由类组成,而 Clojure 作为一个函数式语言,主体是函数,通过 namespace 来封装、隔离函数,你可能会想当然的认为每个 namespace...IPersistentVector ret = PersistentVector.EMPTY; for (int i = 0; i < args.count(); i++) // 这里递归的求列表中每项的值

    99830

    Clojure 学习入门(11)—— 宏 macro

    clojure macro宏在运行之前机械展开,定义宏相当于给语言增加新特性,写宏的*原则*:  能写成函数就不要用宏(因为写宏没有写函数简单直观,容易写错,需要先在 REPL 中测试一番) ...只有不得不用时才用宏(性能要求高比函数调用快,或者需要“代码数据”相互转换)  精心设计的宏调用比函数调用更 DSL(如实现控制结构、传递 Java方法)  宏与函数 ;; 宏正确写法 (defmacro.../macroexpand-all '(op3 5 + 2 * 10))) ;; (op3 5 + 2 * 10) 说明:  正确的宏写法,需要添加 list,宏用defmacro定义,不用宏写法的函数用...defn定义 调试宏,用macroexpand展开 宏符号 ` 原原本本地直译过去,不用`,let语句不被翻译,例如: (let [datastr '{:a 1 :b 2}]) ~' 后面的变量被直接翻译过去...,后面传递的是参数,使用 ~' 修饰直接翻译过去,即字符串传字符串,:dict 键值也传键值 with-dict 传递多个参数给body,其中 dbname tbname 在 with-dict 中被重新赋值

    1K20

    Clojure 学习入门(18)—— 数据类型

    Clojure的类型既简单又复杂。Clojure的本身只有少量不同的类型,而且Clojure不是面向对象语言,它本身并不支创建新的用户自定义类型。一般来说,这让事情非常简单。...幸运的是,通常你只需要在Clojure中关联Java代码关注它。 表4-1....当nil用于布尔表达式计算和空判断永远返回false,但是它不等于它自己。 它可用于任何数据类型,包括原语。但是,传递nil给大多数函数或操作将导致一个错误,因为它不是一个真正的值。...---- 在涉及到不同类型的数字的运算Clojure会自动将结果转换到最精确的类型。例如,当整数和浮点数相乘,结果将是浮点数。...首先,Clojure读取程序将它作为一个列表来解析,然后将其第一个元素(在这里是println)作为函数来对它求值,然后将剩余的部分 ("Hello World!")作为参数传递给它。

    2.3K10

    如何高效地学习编程语言

    这是Clojure好书《Clojure for the Brave and True》作者 Daniel Higginbotham 写于2017年4月16日的博文。...当你重新看地图,确切的地点立马映入眼帘。 我们曾经都有过这样的经验,在洗澡的时候突发灵感。现在你对于为什么这么做有了更好的了解,那么也就能刻意地使用这个技巧。...如果你写的代码不起作用,坦率地向自己或者别人说明你期望的结果。使用科学的方法,就非预期行为的根因提出一个假说。然后测试你的假说。再次试验后,如果依然解决不了,就把这个问题放到一边,待会儿回来。...Ansible 希望你把服务器的整备工作想成定义最终状态,而不是定义抵达那种状态所要采取的步骤。 工具的内部模型就是如何将输入到其接口转换成一些底层的抽象。...Clojure 把 Lisp 转换成 JVM 的字节码。Ansible 把任务定义转换成了 shell 命令。

    1K60

    机器学习各语言领域工具库中文版汇总

    序列分析 ToPS – 这是一个面向对象的框架,有助于在用户定义的字母表上整合序列的概率模型。...斯坦福令牌正则表达式 – 标记器将文本划分成一系列令牌,大致对应于“单词” 斯坦福时代标签 – SUTime是识别和规范时间表达式的库。...Encog中包含用于创建各种网络,以及规范和处理数据的神经网络Encog训练采用多线程弹性的传播方式。Encog还可以利用GPU的进一步加快处理时间。有基于GUI的工作台。...breze – 基于Theano的深度神经网络 pyhsmm -贝叶斯隐马尔可夫模型近似无监督的推理和显式时长隐半马尔可夫模型,专注于贝叶斯非参数扩展,HDP-HMM和HDP-HSMM,大多是弱极限近似...Encog包含创建各种网络的类,以及支持类来规范和处理这些神经网络的数据。使用多线程弹性传播的火车。Encog还可以利用GPU来进一步加快处理时间。

    2.3K11

    《Scala程序设计》阅读书摘

    JVM语言 JVM上的语言越来越多了,从前几年的groovy、Scala和Clojure,现在又听说一门Kotlin。...团队在推广使用Scala之前,要首先学习它的语言规范(官方的没有?...�类型推导:Scala不同于其他静态类型语言,它不要求开发者提供冗余的类型信息,定义变量的时候使用var和val,但是scalac会进行类型推导,检查类型引用是否得当。...这点使得Scala既有动态语言的自由,又能在编译发现不少类型错误。 函数值和闭包:函数可以当作参数传递给函数,可以从函数中返回,甚至可以在函数中嵌套,这些高阶函数称之为函数值。...闭包是一种特殊的函数值,闭包中封闭或绑定了在另一个作用域获上下文中定义的变量。

    87220

    如何高效地学习编程语言

    这是Clojure好书《Clojure for the Brave and True》作者 Daniel Higginbotham 写于2017年4月16日的博文。...当你重新看地图,确切的地点立马映入眼帘。 我们曾经都有过这样的经验,在洗澡的时候突发灵感。现在你对于为什么这么做有了更好的了解,那么也就能刻意地使用这个技巧。...如果你写的代码不起作用,坦率地向自己或者别人说明你期望的结果。使用科学的方法,就非预期行为的根因提出一个假说。然后测试你的假说。再次试验后,如果依然解决不了,就把这个问题放到一边,待会儿回来。...Clojure 的外部模型就是一个 Lisp,它想让你把编程当做大部分以数据为中心,不可变的转换过程。Ansible 希望你把服务器的整备工作想成定义最终状态,而不是定义抵达那种状态所要采取的步骤。...Clojure 把 Lisp 转换成 JVM 的字节码。Ansible 把任务定义转换成了 shell 命令。

    72040

    Java与Scala如何编译Lambda表达式?

    基于JVM的语言(如Scala,Groovy和Clojure)已将它们集成为语言的关键部分,本文将会对比Java与Scala在编译Lambda表达式上存在的差异 Lambda表达式在过去几年中风靡编程世界...基于JVM的语言(如Scala,Groovy和Clojure)已将它们集成为语言的关键部分,Java自然也不甘落后。...有趣的是,虽然Lambda被定义为我们方法的一个组成部分,但实际上它完全存在于我们的课程之外。...这个新表实际上在几年后第一次改变了字节码规范的结构,这要求我们也将Takipi的错误分析引擎改编成它。 02 Lambda代码 这是实际Lambda表达式的代码。...请注意,它被编译为静态函数,以避免像我们在Scala中看到的那样将其他对象传递给它。

    1.4K10

    Clojure component 设计哲学

    内存式缓存:在一个共享的可变引用当中获取或者设置数据的函数,比如 Clojure 中的 Atom 或 Ref。 Component 和面向对象编程里的对象定义在理念上很类似。...Component 假设所有的应用状态都是通过参数的形式传递给使用到它的函数中的。这样会导致很难应用到那些依赖全局或者单例引用的代码。...然后把这个闭包作为 handler 传递给 web 框架。 大部分 web 框架或者类库都会提供一个静态的defroutes或者类似的宏会提供一个相等的非静态的routes方法来创建一个闭包。...幂等 你可能发现了把 start 和 stop 方法定义成幂等的是很有用的。例如,仅仅当 component 没有启动或者没有关闭才进行操作。...(stop) (refresh :after 'user/go)) 使用说明 不要把 system 到处乱传 顶级的system记录只是用来启停其它 component 的,主要是为了交互开发比较方便

    1K00
    领券