我熟悉C和C++的语法是上下文相关的事实,特别是你需要在C中使用"lexer hack".另一方面,我的印象是你只能解析Java尽管两种语言之间存在相当大的相似性,但仍有2个前瞻性令牌.
你需要改变什么才能使它更易于解析?
我问,因为我所见过的关于C的上下文敏感性的所有例子在技术上都是允许的,但非常奇怪.例如,
foo (a);
Run Code Online (Sandbox Code Playgroud)
可以foo用参数调用void函数a.或者,它可以声明a是一个类型的对象foo,但你可以很容易地摆脱parantheses.在某种程度上,这种奇怪之处的发生是因为C语法的"直接声明者"生成规则实现了声明函数和变量的双重目的.
另一方面,Java语法具有用于变量声明和函数声明的单独生成规则.如果你写
foo a;
Run Code Online (Sandbox Code Playgroud)
然后你知道它是一个变量声明,foo可以毫不含糊地解析为一个类型名.如果foo尚未在当前作用域中的某处定义类,则这可能不是有效代码,但这是可以在稍后的编译器传递中执行的语义分析的工作.
我已经看到它说由于typedef很难解析C,但你也可以在Java中声明自己的类型.此外direct_declarator,哪种C语法规则有错?
我在Common Lisp中使用外部包进行项目; 我希望能够使用该软件包,但将其别名为一个较短的名称,类似于我可以做的Clojure
(require '[unnecessarily-long-package-name :as ulpn])
Run Code Online (Sandbox Code Playgroud)
为了避免命名冲突,我宁愿不这样做:
(defpackage #:my-package
(:use #:cl #:other-package))
(in-package :my-package)
(take-over-world "pinky" "brain")
Run Code Online (Sandbox Code Playgroud)
在哪里other-package定义take-over-world.我每次都可以输入完整的合格包名称:
(defpackage #:my-package
(:use #:cl))
(in-package :my-package)
(other-package:take-over-world "pinky" "brain")
Run Code Online (Sandbox Code Playgroud)
但在我的情况下,我导入的包有一个不必要的长名称.有没有办法可以other-package用作
(op:take-over-world "pinky" "brain")
Run Code Online (Sandbox Code Playgroud)
通过别名来op?在Practical Common Lisp的相关章节中,我无法找到类似的内容.
因为我见过到目前为止,Clojure的核心功能几乎都是针对不同类型的集合,例如工作conj,first,rest等我有点疑惑,为什么disj和dissoc是不同的,虽然; 他们有完全相同的签名:
(dissoc map) (dissoc map key) (dissoc map key & ks)
(disj set) (disj set key) (disj set key & ks)
Run Code Online (Sandbox Code Playgroud)
和相当类似的语义.为什么这些都不是由同一个功能覆盖?我能看到的唯一一个支持这一点的论点是,map既有(assoc map key val)并且都有(conj map [key val])添加条目,而set只支持(conj set k).
我可以编写一个单行函数来处理这种情况,但是Clojure在很多时候都是如此优雅,以至于每当它不是:)时它真的很刺激我
我正在使用 Rails 编写一个网络应用程序,其中一部分包括让用户能够留下评论。我想在模型中进行验证,review以确保一个用户不能对同一项目留下多个评论,所以我写了这样的:
class NoDuplicateReviewValidator < ActiveModel::Validator
def validate(record)
dup_reviews = Review.where({user_id: record.user,
work_id: record.work})
unless dup_reviews.length < 1
record.errors[:duplicate] << "No duplicate reviews!"
end
end
end
Run Code Online (Sandbox Code Playgroud)
该验证器具有所需的行为,即它保证用户不能对作品进行两次审查。然而,它有一个不受欢迎的副作用,即用户无法更新他/她留下的现有评论。我正在使用一个非常简单的
def update
@review.update(review_params)
respond_with(@work)
end
Run Code Online (Sandbox Code Playgroud)
在评论控制器中。如何更改验证器或更新方法,以便防止重复审查但允许更新?
我对 Rails 和 Web 开发非常陌生,所以我确信我在这里做了一些愚蠢的事情。我没有使用内置unique验证器之一,因为唯一的是user/work对;同一用户对不同作品可以有多个评论,不同用户对同一作品也可以有多个评论。
我在Fortran 2003中编写了一些代码,它使用稀疏矩阵执行大量线性代数.我正在尝试利用新标准的一些更抽象的功能,所以我有更简单的程序,没有太多的重复代码.
我有一个过程solver,它接受一个矩阵,一些向量,使用的迭代方法的容差等.我传递一个指向一个调用matvec它的过程的指针; matvec是我们用于矩阵向量乘法的子程序.
问题是,有时候matvec这个过程会在colorlist, color1, color2发送到此过程的常规参数之上引入额外的参数.我可以想到几种处理这个问题的方法.
第一个想法:定义两个不同的抽象接口matvec1,matvec2和两个不同的解算器.这有效,但它意味着复制一些代码,这正是我想要避免的.
另一个想法:保持同样的抽象接口matvec,并进行额外的参数colorlist,color1,color2可选的.这意味着在每个matvec例程中都可以选择它们 - 甚至是那些它们不是真正可选的例程,以及它们甚至根本不用的例程.如果我这样做,我肯定会下地狱.
我可以想到许多其他不太理想的解决方案.我想对此有所了解 - 我确信有一些优雅的方法可以做到,我只是不确定它是什么.
我正在写一些线性代数代码(在Fortran 2003的,但它会是同样的问题,用Fortran 90或C)需要几个工作向量做计算的,我的想法来处理,这是做一个工作阵列w(:,:),其对于线性代数模块是私有的,即在本讨论中定义的"隐藏全局" ,为什么真正的全局变量是可怕的.
我想这就像在黑板上解决一个大问题一样,对于问题的每个部分,你选择黑板区域来解决它.
根据这个类比,我还可以拥有一堆小白板:定义work_array数据类型并根据需要将它们传递给求解器.(PETSc通过另一个抽象层有效地使用这种方法; a solver是一种数据类型,它包括一些指向所用方法的过程指针以及一些工作向量.)当存在从一个求解器到另一个求解器的嵌套调用时,它得到一个螨虫很复杂,所以我喜欢第一种方式更好.它也不需要那么多误导.
有关哪种方法可以更好地编程实践的想法?
编辑:当我开始使用OpenMP时,我也不认为这将是一个问题,我已经在这个代码的旧版本中完成了.在设置问题后,每个线程只访问其未知数的部分而不访问其他线程的部分.尽管如此,并发问题可能是一般不使用静态变量的好理由.
如果每次调用求解器时都必须为scratch数组动态分配空间,这通常不会产生很多开销吗?
我正在使用CMake进行中等规模的Fortran项目; 有时我用gfortran构建它,有时用ifort构建它.当我想进行调试构建时,编译器标志是不同的; 我想让CMake自动检查正在使用哪个编译器并相应地设置标志.
看起来这个答案显示了如何为不同的C++编译器做同样的事情.有一个如何使用Fortran检查编译器的示例
if (Fortran_COMPILER_NAME MATCHES "gfortran.*")
Run Code Online (Sandbox Code Playgroud)
但是,这无法调用条件,因为CMake决定使用f95.当然,f95碰巧别名gfortran,但CMake没有检测到.
这样做的正确方法是什么?
在 Clojure 中,哈希映射和向量实现了invoke,因此它们可以用作函数,例如
(let [dict {:species "Ursus horribilis"
:ornery :true
:diet "You"}]
(dict :diet))
lein> "You"
Run Code Online (Sandbox Code Playgroud)
或者,对于向量,
(let [v [42 613 28]]
(v 1))
lein> 613
Run Code Online (Sandbox Code Playgroud)
可以通过让它们实现 Clojure 中的可调用对象IFn。我是 Common Lisp 的新手——可调用对象是否可能,如果是的话,实现它会涉及什么?我真的很想能够做这样的事情
(let ((A (make-array (list n n) ...)))
(loop for i from 0 to n
for j from 0 to m
do (setf (A i j) (something i j)))
A)
Run Code Online (Sandbox Code Playgroud)
而不是让代码乱七八糟aref。同样,如果您可以以相同的方式访问其他数据结构的条目,例如字典,那将会很酷。
我已经查看了Lisp/Scheme 中函数对象的wiki 条目,似乎拥有一个单独的函数命名空间会使 CL 的问题复杂化,而在 Scheme 中,您可以使用闭包来做到这一点。
我有一些Fortran代码,我正在与MPI并行化,这正在做着真正奇怪的事情.首先,我有一个变量nstartg,我从老板流程向所有工人广播:
call mpi_bcast(nstartg,1,mpi_integer,0,mpi_comm_world,ierr)
Run Code Online (Sandbox Code Playgroud)
该程序中的变量nstartg永远不会再次更改.后来,我让老板进程向工人发送eproc一个数组元素edge:
if (me==0) then
do n=1,ntasks-1
(determine the starting point estart and the number eproc
of values to send)
call mpi_send(edge(estart),eproc,mpi_integer,n,n,mpi_comm_world,ierr)
enddo
endif
Run Code Online (Sandbox Code Playgroud)
如果me非零,则匹配的receive语句.(为了便于阅读,我遗漏了一些其他代码;我有一个很好的理由不使用scatterv.)
事情变得奇怪:变量nstartg被改变n而不是保持其实际值.例如,在进程1上,在mpi_recv之后nstartg = 1,在进程2上它等于2,依此类推.此外,如果我将上面的代码更改为
call mpi_send(edge(estart),eproc,mpi_integer,n,n+1234567,mpi_comm_world,ierr)
Run Code Online (Sandbox Code Playgroud)
并在匹配调用mpi_recv时相应地更改标记,然后在进程1,nstartg = 1234568; 在过程2,nstartg = 1234569等
到底是怎么回事?我改变的是mpi_send/recv用于识别消息的标签; 如果标签是唯一的,那么消息不会混淆,这不应该改变任何东西,但它改变了一个完全不相关的变量.
在老板的过程中,nstartg没有改变,所以我可以通过再次播放来解决这个问题,但这不是一个真正的解决方案.最后,我应该提一下,使用电栅编译和运行此代码并没有发现任何缓冲区溢出,也没有--fbounds-check向我抛出任何东西.
我正在尝试在 Fortran 中模拟 C 断言,以便强制执行所有过程的前置条件和后置条件。通过这种方式,我可以向用户提供有关运行时错误的更详细的信息,而不是我可以合理预期维护的信息。
为了实现这一点,我使用了预处理器指令__FILE__和__LINE__,并定义了一个assert扩展为 Fortran 子例程调用的宏。我没有尝试在这里描述它,而是创建了一个git 存储库,其中包含一些示例代码。如果你用它来构建它
make test
./test
Run Code Online (Sandbox Code Playgroud)
该函数挂起,因为您调用的函数需要正参数和负参数。但是,如果您使用
make test DEBUG=1
./test
Run Code Online (Sandbox Code Playgroud)
错误被断言捕获。
这适用于 gfortran 和 Intel Fortran 编译器。我无法访问其他 Fortran 编译器。如果文件扩展名是 ,我可以合理地期望其他编译器进行必要的源预处理吗.F90?或者我应该依靠旗帜-cpp?最便携的方法是什么?我到底应该这样做吗?
fortran ×5
clojure ×3
c ×2
common-lisp ×2
oop ×2
activerecord ×1
cmake ×1
fortran90 ×1
grammar ×1
java ×1
lisp-2 ×1
mpi ×1
parsing ×1
polymorphism ×1
preprocessor ×1
validation ×1