Есть ли язык программирования, который позволяет объявление переменных на сайте вызова? - PullRequest
0 голосов
/ 26 октября 2009

Обновление 2: примеры удалены, поскольку они вводили в заблуждение. Те, что ниже, более актуальны.

Мой вопрос:

Есть ли язык программирования с такой конструкцией?

Обновление: Теперь, когда я думаю об этом, у Пролога есть нечто подобное. Я даже позволяю определять операции в строке определения. (забудьте о возврате и отношениях - подумайте о синтаксисе)

Я задал этот вопрос, потому что считаю, что хорошо иметь симметрию в языке. Симметрия между параметрами "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", _))

Или в стиле функционал + пролог

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

В предлагаемом языке нет выражений, потому что все возвраты осуществляются через параметры. Это было бы обременительно в ситуациях, когда глубокие иерархические вызовы функций естественны. Пример с Лиспом:

(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 ]

3 голосов
/ 26 октября 2009
<?php
function f($param, &$ret) {
    $ret = $param . $param;
}

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

?>

$ дважды видно после вызова f (), и оно имеет ожидаемое значение. При удалении амперсанда возникают ошибки. Похоже, что PHP объявит переменную в точке вызова. Я не уверен, что это вас сильно покупает, особенно в PHP.

2 голосов
/ 27 октября 2009

Для вашего первого фрагмента кода я не знаю ни одного из таких языков, и, честно говоря, я рад, что это так. Объявление переменной в середине выражения таким образом, а затем использование ее вне указанного выражения выглядит для меня очень неправильно. Во всяком случае, я бы ожидал, что область действия такой переменной будет ограничена вызовом функции, но, конечно, это, во-первых, совершенно бессмысленно.

Для второго - множественные возвращаемые значения - практически любой язык с поддержкой кортежей первого класса имеет что-то близкое к этому. Например. 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 относится и к нему. Но он также может имитировать возврат кортежей для методов, которые были объявлены в C # или VB с out или ref аргументами, что, вероятно, наиболее близко к тому, что вы описываете - хотя это все еще неявно (т.е. вы не указываете -аргумент вообще, даже как _). Пример:

 // 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)
2 голосов
/ 27 октября 2009

Мне трудно понять, что вы хотите. Вы хотите поставить тип возврата в подписи вызова? Я уверен, что кто-то может взломать это вместе, но действительно ли это полезно?

// 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
2 голосов
/ 26 октября 2009

«Существует ли язык программирования с такой конструкцией?»

Ваш вопрос на самом деле немного неясен.

В некотором смысле, любой язык, который поддерживает присвоение [состояния переменной, связанного с] аргументом функции, поддерживает "такую ​​конструкцию".

C поддерживает это, потому что «void f (type * address)» позволяет изменять любой адрес, на который указывает. Java поддерживает это, потому что «void f (Object x)» допускает любой (изменяющий состояние) вызов некоторого метода x. COBOL поддерживает это, потому что «PROCEDURE DIVISION USING X» может включать X, который содержит указатель / адрес памяти, что в конечном итоге позволяет изменить состояние объекта, на который указывает этот адрес.

С этой точки зрения я бы сказал, что почти все языки, известные человечеству, поддерживают «такую ​​конструкцию», за исключением, возможно, таких языков, как Tutorial D, которые утверждают, что они «абсолютно без указателей».

1 голос
/ 31 октября 2009

Возможно, вы посмотрите на Oz . В Oz у вас есть только процедуры, и вы присваиваете значения переменным, а не возвращаете их.

Это выглядит так:

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

Есть функции (которые возвращают значения), но это только синтаксический сахар.

Кроме того, Концепции, методы и модели компьютерного программирования - это великолепная книга, подобная SICP, которая обучает программированию с использованием Oz и системы программирования Моцарта.

1 голос
/ 28 октября 2009

Не языки программирования, но различные исчисления процессов имеют синтаксис для привязки имен на сайтах вызовов получателей в зависимости от выражений процессов, зависящих от них. Хотя Pict имеет такой синтаксис, на самом деле он не имеет смысла в производном функциональном синтаксисе, о котором вы спрашиваете.

1 голос
/ 27 октября 2009

Вот как бы вы сделали это в 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;

[править] Кроме того, поскольку вас интересует минимальный синтаксис:

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, которые могут вас заинтересовать. [/ Править]

Я не уверен, чего именно вы пытаетесь достичь с помощью второго примера, но концепция неявных переменных существует в нескольких языках, в 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, чтобы избежать многократной передачи временных переменных в функции

0 голосов
/ 27 октября 2009

Несколько сбивает с толку, но C ++ вполне доволен объявлением переменных и передачей их как параметров в одном выражении:

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

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

Но не делайте этого вне конкурсов запутывания.

Возможно, вы также захотите взглянуть на передать по имени семантику в Алголе, которая в вашем полном описании пахнет примерно так.

0 голосов
/ 26 октября 2009

Я так не думаю. Большинство языков, которые делают что-то подобное, используют Tuples, так что может быть несколько возвращаемых значений. Если подумать, то эталонные и выходные параметры в стиле C в основном взломаны и не собираются возвращать кортежи ...

...