小编art*_*ter的帖子

Lisp-family:如何逃避面向对象的java式思维?

背景故事:我在Java中做了很多大型且相对复杂的项目,在嵌入式C编程方面有很多经验.我已经熟悉了scheme和CL语法,并用racket编写了一些简单的程序.

问题:我已经计划了一个相当大的项目,并希望在球拍中做到这一点.我听说过很多的"如果'获取’口齿不清,你会成为一个更好的程序员"等,但每一次我尝试计划或编写一个程序我还是"分解"的任务与接口熟悉的有状态的对象时.
是否有针对lisp的"设计模式"?如何"获得"lisp-family"mojo"?如何逃避面向对象约束你的思考?如何运用强大的宏观设施推动的功能性编程思想?我尝试在github上研究大项目的源代码(例如Light Table)并且更加困惑,而不是开悟.
EDIT1(不那么暧昧的问题):关于这个主题是否有很好的文献,你可以推荐或者是否有用cl/scheme/clojure编写的高质量的开源项目,可以作为一个很好的例子吗?

lisp scheme functional-programming clojure racket

11
推荐指数
2
解决办法
500
查看次数

呈现高度细化和“缩小”的数据

互联网上有一个 gif,其中有人使用某种 CAD 并在其中绘制了多个矢量图片。在第一帧中,他们放大了一个小点,显示出一个全新的不同比例的矢量图片,然后他们继续放大另一个小点,显示另一张详细的图片,重复几次。这是 gif 的链接
或另一个类似的示例:假设您有一个时间序列,每个样本的粒度为 1 毫秒,然后缩小以显示数年的数据。

我的问题是:当大量数据最终混叠成单个像素时,如此精细的数据最终如何呈现。
您是否必须通过整个数据集来渲染该像素(即在时间序列的情况下:通过数百万条记录将它们平均为 1 行,或者在 CAD 渲染整个矢量图片并将其模糊成小点的情况下) ,或者可以应用某些详细级别的优化,这样您就不必这样做了?
如果是这样,它们是如何工作的?在哪里可以了解它?

plot rendering time-series cad

8
推荐指数
1
解决办法
139
查看次数

代码为系统映像(序列化运行时环境)vs源(文本)

今天几乎所有传统语言都将程序员的意图表示为文本源,然后(为简单起见)将其转换为某些字节码/机器代码并由VM/CPU解释/执行.
还有另一种技术,出于某种原因,它并不是流行的日子:"冻结"VM的运行时间并将环境(符号绑定,状态,代码(无论是什么))转储/序列化为图像,然后您可以传输,加载和执行.因此,您不能以通常的方式"编写"代码,而是在"运行时"中使用新符号修改环境.
我看到这项技术的巨大优势:

  • 功率提升的REPL:您可以在编写代码时自省代码,部分评估代码,直接测试代码并查看更改的效果.如果你搞砸了再做一遍,或者最后将它提交给环境,那就回滚一下.无需长编译运行调试周期;
  • 关于动态语言的一些常见问题(它们无法编译,因为编译器无法静态推理环境)被忽略了:解释器知道所在的位置,并且可以用静态偏移替换符号引用并进行其他优化;
  • 程序员的大脑更容易:你从头脑中"卸载"有关代码的不同上下文信息,即你​​不需要跟踪你的代码已经对某些变量/数据结构做了什么,或者哪个变量保存了什么:你看到了它直接在你眼前!通常的方式(编写源代码),程序员在代码中添加新的抽象或注释以澄清意图,但这可能(并且将会)变得混乱.

问题是:这种方法的缺点是什么?我没有看到任何严重的劣势吗?我知道,它有一些问题,即:

  • 尝试用它构建一个模块系统,这不会导致依赖地狱或严重的链接问题
  • 安全问题
  • 尝试对这些图像进行版本控制并启用并发开发

但是,这些是,恕我直言,可以用一个好的设计解决.

EDIT1:关于"已关闭,主要是基于意见"的状态.我已经描述了两种现有的方法,很明显,一种方法比另一方更受欢迎.我不知道其原因是纯粹的"以意见为基础"还是有研究支持,但是即使他们是以意见为基础的,如果有人将这些意见列为开发的原因,那么实际上应该回答我的问题.

lisp smalltalk selflanguage vm-implementation

5
推荐指数
1
解决办法
92
查看次数

理解(子、部分、完整、一次性)延续(用过程语言)

在阅读了几乎所有我能找到的有关延续的内容后,我仍然无法理解它们。也许是因为所有的解释都与 lambda 演算密切相关,我很难理解它。

一般来说,延续是在完成当前操作(即其余计算)后下一步要做什么的某种表示。

但随着种类繁多,事情变得更加棘手。也许你们中的一些人可以帮助我用我的自定义类比来帮助我,并指出我在理解中犯了错误的地方。

假设我们的函数被表示为对象,为了简单起见:

  1. 我们的解释器有一堆函数调用。
  2. 每个函数调用都有一个用于存储本地数据和参数的堆栈。
  3. 每个函数调用都有一个要执行的“指令”队列,这些指令对本地数据堆栈和队列本身(也可能对调用者堆栈进行操作)进行操作。

该类比类似于XY 连接语言

所以,根据我的理解:

  • 延续是整个计算的其余部分(未完成的指令队列+所有后续计算的堆栈:调用者队列)。
  • 部分延续是当前未完成的队列+调用者堆栈的某些分隔部分,直到某个点(对于整个程序来说不是完整的)。
  • 子延续是当前“活动”函数的当前指令队列的其余部分。
  • 一次性延续是指在具体化为对象后只能执行一次的延续。

如果我的类比有误,请纠正我。

continuations procedural-programming functional-programming

5
推荐指数
1
解决办法
1324
查看次数

编译到汇编时最大限度地减少跳转量

假设我们已经将一些程序编译成一些抽象的中间语言:我们的程序是一系列操作和决策(分支),下一步要执行的操作(基本上是一棵树).例:

a();
if (bla) then c();
else b(); d();
e();
Run Code Online (Sandbox Code Playgroud)

现在我们需要将这个序列"打包"到我们的线性内存中,通过这样做,我们的代码必须分支(有条件而不是).例如,可能性之一:

      CALL A
      TEST bla
      BRANCH else
      CALL C
      JMP esc
else: CALL B
      CALL D
esc:  CALL E
Run Code Online (Sandbox Code Playgroud)

关于如何在线性存储器中布置这些块当然有多种可能性,并且它们在分支/跳跃量方面都不同.我们的目标是尽量减少它们.
问题:
a)如何调用此问题?它有一般的名称吗?(它是BDD构造的一个实例吗?)
b)这种问题的复杂性是什么(找到一个块的排列,使得跳跃/分支的数量最小)?

compiler-construction assembly compilation

4
推荐指数
1
解决办法
61
查看次数

X86预取优化:"计算goto"线程代码

我有一个相当重要的问题,我的计算图有周期和多个"计算路径".我没有做一个调度程序循环,每个顶点将被逐个调用,我有一个想法是将所有预先分配的"框架对象"放在堆中(代码+数据).
这有点类似于线程代码(甚至更好:CPS),只是在堆中跳转,执行代码.每个代码段与堆中自己的"帧指针"相关联,并使用与之相关的数据.帧始终保持分配状态.代码只在已知位置产生副作用,计算(如果需要)下一个goto值并跳转到那里.
我还没有尝试过(这将是一个重要的事情,使它正确,我完全意识到所有的困难)所以我想问x86机械专家:它能比调度程序循环更快吗?我知道在硬件中进行的调用/返回指令有几种优化.
访问相对于堆栈指针的数据或任何其他指针之间有区别吗?是否有预取间接跳转(跳转到存储在寄存器中的值?).
这个想法是否可行?

PS如果你已经读过这个并且仍然无法理解这个想法的意思(原谅我尝试解释事情的失败)想象这整个就像是一堆堆上的预先分配的协同程序,彼此相互影响.标准x86堆栈未在进程中使用,因为所有内容都在堆上.

x86 assembly prefetch

3
推荐指数
1
解决办法
378
查看次数

Lisp-family:对符号调用和符号的不同评估作为参数

在lisp-family(EDIT:lisp-1)语言中是否有一种方法可以区分符号评估关于其作为函数或作为参数的位置(即,在评估它时,覆盖此符号的eval)?
作为一个例子(我不需要这个功能,这是一个例子),我想对一组对象实现某种中缀操作,这可以由对象本身调用

(my-obj some-operator arg1 ...)  
Run Code Online (Sandbox Code Playgroud)

这实际上将函数some-operator应用于my-obj和arguments.
但是当这个对象在代码中的任何其他位置用作参数时,例如:

(some-function my-obj &args...) 
Run Code Online (Sandbox Code Playgroud)

它将评估为my-obj的值.
谢谢.

lisp scheme clojure s-expression racket

1
推荐指数
1
解决办法
106
查看次数

Verilog:设置串联运算符内的表达式宽度

所以,问题是我需要在循环内用字节模式初始化一个 32 位字的数组,其中循环变量的尺寸非常糟糕(不是我的代码)。因为这是一个快速破解,所以我不想重构循环,只是为了尝试测试代码。因此,可行的解决方案是执行以下操作:

reg [15:0] index;
reg [31:0] data_word;
for (index = 0 ; index < buflen ; index = index+1) begin
  data_dword = (((index*4+'h13)&8'hFF) << 24) | (((index*4+'h14)&8'hFF) << 16) | (((index*4+'h15)&8'hFF) << 8) | (((index*4+'h16)&8'hFF) << 0);
  //I expect to get something like 32'h13141516, 32'h1718191a
end
Run Code Online (Sandbox Code Playgroud)

我想我也许可以使用串联运算符:

data_dword = {((index*4+'h13)&8'hFF), ((index*4+'h14)&8'hFF), ((index*4+'h15)&8'hFF), ((index*4+'h16)&8'hFF)};
Run Code Online (Sandbox Code Playgroud)

但这不能正常工作。我得到 32'h00000016、32'h0000001a 等。即只有最后一个字节可用,所有其他字节都被覆盖。为什么这样?我认为每个子表达式的长度:

((index*4+'h13)&8'hFF)
Run Code Online (Sandbox Code Playgroud)

未正确调整(由于某种原因是 32 位),因此整体串联被截断。

verilog system-verilog

1
推荐指数
1
解决办法
1556
查看次数