是否有一种编程语言允许在呼叫站点进行变量声明?

时间:2009-10-26 20:37:23

标签: language-agnostic syntax language-design language-construct

更新2:示例已删除,因为它们具有误导性。以下内容更具相关性。

我的问题:

是否有编程语言有这样的构造?

更新 现在,当我想到它时,Prolog有类似的东西。 我甚至允许在定义行定义操作。 (忘记回溯和关系 - 考虑语法)

我问了这个问题,因为我相信,在语言中保持对称是件好事。 “in”参数和“out”参数之间的对称性。

如果返回这样的值很容易,我们可以用设计语言删除显式返回。

回复对......我认为这是一个黑客攻击。我们不需要数据结构来将多个参数传递给函数。

更新2:

举一个我正在寻找的语法示例:

f (s, d&) = // & indicates 'out' variable
  d = s+s.

main =
  f("say twice", &twice)  // & indicates 'out' variable declaration
  print(twice)


main2 =
  print (f("say twice", _))

或功能+ prolog风格

f $s (s+s).    // use $ to mark that s will get it's value in other part of the code

main =
  f "say twice" $twice  // on call site the second parameter will get it's value from 
  print twice

main2 =
  print (f "Say twice" $_) // anonymous variable

在提议的语言中,没有表达式,因为所有返回都是通过参数。在深层次函数调用是自然的情况下,这将是麻烦的。 Lisp'ish示例:

(let x (* (+ 1 2) (+ 3 4)))  // equivalent to C x = ((1 + 2) * (3 + 4))

将需要所有临时变量的语言名称:

+ 1 2 res1
+ 3 4 res2
* res1 res2 x

所以我提出了将整个函数调用转换为该变量值的匿名变量:

* (+ 1 2 _) (+ 3 4 _)

这不是很自然,因为我们拥有所有的文化包袱,但我想抛弃关于我们目前语法的所有先入之见。

9 个答案:

答案 0 :(得分:3)

<?php
function f($param, &$ret) {
    $ret = $param . $param;
}

f("say twice", $twice);
echo $twice;

?>
在调用f()之后看到$ p两次,并且它具有预期值。如果删除“&”符号,则会出现错误。所以看起来PHP会在调用时声明变量。不过,我不相信你买得太多,特别是在PHP中。

答案 1 :(得分:2)

“有这种构造的编程语言吗?”

你的问题实际上有点不清楚。

从某种意义上说,任何支持[与函数参数相关的变量状态]赋值的语言都支持“这样的构造”。

C支持它,因为“void f(type * address)”允许修改任何地址点。 Java支持它,因为“void f(Object x)”允许对x的某些方法进行任何(状态修改)调用。 COBOL支持它,因为“使用X的过程分区”可能涉及一个包含指针/内存地址的X,最终允许更改该地址所指向的东西的状态。

从这个角度来看,我会说人类已知的几乎所有语言都支持“这样的结构”,除了教程D这样的语言之外,它们声称“绝对没有指针”。

答案 2 :(得分:2)

我很难理解你想要的东西。您想将返回类型设置为呼叫签名吗?我敢肯定有人可以一起破解,但它真的有用吗?

// fakelang example - use a ; to separate ins and outs
function f(int in1, int in2; int out1, int out2, int out3) {...}

// C++0x-ish
auto f(int in1, int in2) -> int o1, int o2, int o3 {...}

int a, b, c;
a, b, c = f(1, 2);

我觉得这将以这种方式在内部实施:

LEA EAX, c  // push output parameter pointers first, in reverse order
PUSH EAX
LEA EAX, b
PUSH EAX
LEA EAX, a
PUSH EAX
PUSH 1      // push input parameters
PUSH 2
CALL f      // Caller treat the outputs as references
ADD ESP,20  // clean the stack

答案 3 :(得分:2)

对于您的第一个代码段,我不知道任何此类语言,坦率地说,我很高兴是这种情况。在表达式中间声明一个变量,然后在表达式之外使用它,对我来说看起来非常错误。如果有的话,我希望这个变量的范围仅限于函数调用,但当然它首先是毫无意义的。

对于第二个 - 多个返回值 - 几乎所有具有一流元组支持的语言都有接近这一点。例如。的Python:

def foo(x, y):
    return (x + 1), (y + 1)

x, y = foo(1, 2)

Lua没有一流的元组(即你不能将元组值绑定到单个变量 - 你总是需要扩展它,可能会丢弃它的一部分),但它确实有多个返回值,基本上是相同的语法:

function foo(x, y)
    return (x + 1), (y + 1)
end

local x, y = foo(x, y)

F#具有一流的元组,因此之前所说的关于Python的所有内容也适用于它。但它也可以模拟使用outref参数在C#或VB中声明的方法的元组返回,这可能与您描述的最接近 - 尽管它仍然是隐含的(即,你不是t根本指定out-argument,即使是_)。例如:

 // C# definition
 int Foo(int x, int y, out int z)
 {
     z = y + 1;
     return x + 1;
 }

 // explicit F# call
 let mutable y = 0
 let x = Foo(1, 2, byref y);

 // tupled F# call
 let x, y = Foo(1, 2)

答案 4 :(得分:1)

以下是在Perl中执行此操作的方法:

sub f { $_[1] = $_[0] . $_[0] }  #in perl all variables are passed by reference

f("say twice", my $twice);  
# or f("...", our $twice) or f("...", $twice)
  # the last case is only possible if you are not running with "use strict;"

print $twice;

[edit]此外,由于您似乎对最小语法感兴趣:

sub f { $_[1] = $_[0] x 2 }   # x is the repetition operator

f "say twice" => $twice;      # => is a quoting comma, used here just for clarity

print $twice;

完全有效的perl。以下是正常引用逗号用法的示例:

("abc", 1, "d e f", 2)      # is the same as 
(abc => 1, "d e f" => 2)    # the => only quotes perl /\w+/ strings

此外,在返回值上,除非提前退出“返回”,否则所有perl子例程都会自动返回它们执行的最后一行,无论是单个值还是列表。最后,看看perl6的feed运算符,你可能会觉得它很有趣。 [/编辑]

我不确定你在第二个例子中想要实现什么,但隐式变量的概念存在于几种语言中,在Perl中,它是$ _。

一个例子是perl的内置函数,当它们没有参数时会查看$ _。

$string = "my string\n";

for ($string) {      # loads "my string" into $_
    chomp;           # strips the last newline from $_
    s/my/our/;       # substitutes my for our in $_
    print;           # prints $_
}

不使用$ _,上面的代码是:

chomp $string;
$string =~ s/my/our/;
print $string;
在许多情况下,在perl中使用

$ _以避免重复将临时变量传递给函数

答案 5 :(得分:1)

不是编程语言,但是各种进程计算具有在依赖于它们的进程表达式范围内的接收器调用站点处绑定名称的语法。虽然Pict具有这样的语法,但在您要求的派生函数语法中实际上没有意义。

答案 6 :(得分:1)

您可以查看Oz。在Oz中,您只有程序,并且您为变量赋值而不是返回它们。

看起来像这样:

proc {Max X Y Z}
  if X >= Y then Z = X else Z = Y end 
end 

有函数(返回值),但这只是语法糖。

此外,Concepts, Techniques, and Models of Computer Programming是一本非常类似SICP的书,通过使用Oz和莫扎特编程系统来教授编程。

答案 7 :(得分:0)

我不这么认为。大多数使用Tuples的语言都可以使用多个返回值。想想看,C风格的参考和输出参数大多是乱七八糟的,不会回归元组......

答案 8 :(得分:0)

有些令人困惑,但C ++非常满意声明变量并将它们作为out参数传递到同一语句中:

void foo ( int &x, int &y, int &z ) ;

int a,b,c = (foo(a,b,c),c);

但是不要在混淆比赛之外这样做。

您可能还想查看Algol中的pass by name语义,您的更全面的描述与之相似。