LINUX.ORG.RU

передача аргументов не по их номеру в объявлении, а по имени


0

0

Здравствуйте. Мне интересно мнение о наличии смысла у передачи аргументов по имени. Чтобы быть более конкретным, приведу пример:

Пусть существует функция, создающая нового пользователя (create_new_user) и принимающая три аргумента: его имя (login), пароль (password) и уровень доступа (access_lvl). При передачи аргументов по их номеру (как в C), функция будет вызываться так:

create_new_user ("vasya", "p4$$w0rd", 11);

Но если передавать аргументы по имени, возможен такой вариант:

create_new_user (@login "vasya", @password "p4$$w0rd", @access_lvl 11);

Если есть смысл в таком способе указания параметров, следует ли разрешать их передачу по номеру? Как быть с вызовом внешних функций, написанных на языке, не поддерживающим такие вызовы? Как должно выглядить объявление (declaration) такой функции? Разрешать ли не указывать имя аргумента, если он единственный? ... если он последний? ... если он первый?

Зараннее спасибо.

★★★

Забыл сказать, что язык - компилируемый, а функции являются объектами. Причём создать именованную функцию так, как например это делается в C, невозможно - можно присвоить объекту какую-нибудь функцию, как значение: 'func = { 2 + 2 }; (аналогично var func = function() { return 2 + 2; }; в JavaScript).

kmeaw ★★★
() автор топика

Посмотри, как это сделано в питоне и perl6 - они поддерживают как позициональные, так и именованные параметры при вызове.

делать же вызов с именованными параметрами основным и единственным - точно не стоит - много лишней писанины, и код на таком языке в читабельности не выиграет, а проиграет.

anonymous
()

да передай просто один хеш на вход функции

#!/usr/bin/perl

$Params{"login"} = "vasya";
$Params{"password"} = "p4$$w0rd";
$Params{"level"} = 11;

create_new_user (\%Params);

sub create_new_user
{
  my $P = $_[0];
  
  print "Login:    ".$P->{"login"}."\n";
  print "Password: ".$P->{"password"}."\n";
  print "Level:    ".$P->{"level"}."\n";
  
}



$ ./test.pl
Login:    vasya
Password: p4
Level:    11

theserg ★★★
()

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

Насчёт синтаксиса, имхо наиболее естественно выглядит примерно так:
function create_new_user(login, password, access_lvl, create_home_dir = true, home_dir = if (create_home_dir) "/home/" + login else null)
{
}

create_new_user("vasya", "123", 2, false);
create_new_user(password = "222", login = "petya", access_lvl = 3, home_dir = "/usr/home/petya");
create_new_user("vitya", "123", 4, home_dir="/vitya");

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

Legioner ★★★★★
()
Ответ на: комментарий от theserg

косячок с паролем вышел, надо было одинарные ковычки

theserg ★★★
()
Ответ на: комментарий от Legioner

Насчет типизации - существует базовый класс CObject, который наследуется (почти) всеми классами. У класса CObject определён метод "=": он связывает объект (его имя) и значение (аргумент метода). Многие классы переопределяют метод "=" так, чтобы он копировал данные и проверял тип аргумента.

Например:

'z = "Hello";

z = 5; #ОШИБКА

Но так делают далеко не все классы. Например CFunction так не делает.

'f = { io << "Calculating..."; 2 + 2 };

io <<< f(); #Calculating...4

&f = 4;

io <<< f(); #4

Как называется такая типизация? ИМХО это динамическая.

Насчет синтаксиса:

'create_new_user = <@login, @password, @access_lvl, @create_home_dir true, @home_dir { create_home_dir then "/home/\{login}" else null }> -> { ... };

create_new_user($vasya, $123, 2, false);

create_new_user(@password $222, @login $petya, @access_lvl 3, @home_dir $/usr/home/petya);

create_new_user($vitya, $123, 4, @home_dir $/vitya);

Насколько это читабельно? Что следует изменить?

kmeaw ★★★
() автор топика
Ответ на: комментарий от kmeaw

Нечитабельно. Синтаксис выглядит ужасно.
Объявление функции - ужаснах редкостный.
@ и $ не нужны и только загромождают код.
$ - это такой способ экранировать строки? А как передавать строки с пробелами?
"create_home_dir then "/home/\{login}" else null" - тернарный оператор? Чем такой вариант лучше if then else? Отсутствием if?
Передача именованных параметров в функцию очень нечитабельна.
Посмотрите на питон (ну или хотя бы на руби, хотя там тоже с синтаксисом местами грустно) для примера довольно чистого синтаксиса.

anonymous
()
Ответ на: комментарий от anonymous

> Нечитабельно. Синтаксис выглядит ужасно.
> Объявление функции - ужаснах редкостный.
'f = ("x" => CInt, "y" => CString, CInt) -> { ... };
Так лучше?
> @ и $ не нужны и только загромождают код.
Заменить $... на _"..."?
> $ - это такой способ экранировать строки? А как передавать строки с пробелами?
$ - аналог : в Ruby, компилятор разворачивает его в CSymbol new: const_X (а двоеточие уже используется для других целей).
Symbol с пробелом можно создать так: $(..) или так: ${..}, или даже так: $[..]. Строки задаются "вот так" (их можно менять и они являются совсем реальными объектами (под них выделяется память)).
> "create_home_dir then "/home/\{login}" else null" - тернарный оператор? Чем такой вариант лучше if then else? Отсутствием if?
create_home_dir - объект класса CBit, then - метод объекта, "/home/\{login}" - аргумент. 
Получается аналог тернарного оператора. 
Он ничем не лучше if, просто if нет (как и других ключевых слов). 
Может сделать and и or, как синонимы then и else? 
Или добавить "низкоуровневый" условный оператор?
> Передача именованных параметров в функцию очень нечитабельна.
Вариант { :x => 3, :y => 4 } выглядит лучше? 
Или, может, лучше так: f('x = 3, 'y = 4) ?
> Посмотрите на питон (ну или хотя бы на руби, хотя там тоже с синтаксисом местами грустно) для примера довольно чистого синтаксиса.
А в чём конкретно синтаксис Руби плох?
(я не пытаюсь разжечь флейм, просто хочу знать, какие идеи лучше не утаскивать)

Спасибо за критику.

kmeaw ★★★
() автор топика
Ответ на: комментарий от kmeaw

> 'f = ("x" => CInt, "y" => CString, CInt) -> { ... }; > Так лучше?

Что делает ' перед именем функции? зачем имя параметра в кавычках, зачем => и -> ? def f(CInt x, CString y, CInt) { ... } или f = lambda(CInt x, CString y, CInt) { ... } если через неименованную функцию

> Заменить $... на _"..."?

create_new_user(password="222", login="petya", access_lvl=3, home_dir="/usr/home/petya")

> $ - аналог : в Ruby, компилятор разворачивает его в CSymbol new: const_X (а двоеточие уже используется для других целей). > Symbol с пробелом можно создать так: $(..) или так: ${..}, или даже так: $[..]. Строки задаются "вот так" (их можно менять и они являются совсем реальными объектами (под них выделяется память)).

Почему бы не создавать CSymbol просто по наличию "" без $ и :?

> create_home_dir - объект класса CBit, then - метод объекта, "/home/\{login}" - аргумент. > Получается аналог тернарного оператора. > Он ничем не лучше if, просто if нет (как и других ключевых слов). > Может сделать and и or, как синонимы then и else? > Или добавить "низкоуровневый" условный оператор?

Если then это вызов метода, то как-то надо приписать, что это он, хоть через . хоть через -> хоть через что-то еще. Вообще мне никогда не нравились вызовы функций без скобок, они хорошо выглядят только в функциональных языках. Как обратиться к функции именно как к объекту в вашем языке? Например как передать функцию как параметр другой функции? Синонимы лучше не делать - это большое заблуждение, что надо несколько конструкций типа if/unless в руби. Лучше оставлять только один способ выполнить действие, иначе начнется бардак как в перле. С низкоуровневым оператором сложнее. Как вариант можно попробовать все конструкции языка сделать методами.

> Вариант { :x => 3, :y => 4 } выглядит лучше? > Или, может, лучше так: f('x = 3, 'y = 4) ?

см. выше

> 'create_new_user = <@login, @password, @access_lvl, @create_home_dir true, @home_dir { create_home_dir then "/home/\{login}" else null }> -> { ... };

Вот тут я не понял, зачем при объявлении параметров разрешать писать код, куску { create_home_dir then "/home/\{login}" else null } - место в теле функции, но ни как среди объявлений переменных.

Считаю, что не надо загромождать язык лишними конструкциями типа @$:=> - они, в общем-то, не имеют смысла и только ухудшают читаемость. Все написанное - мое ИМХО.

anonymous
()
Ответ на: комментарий от anonymous

> Что делает ' перед именем функции?

Создаёт новый объект класса CObject.

> def f(CInt x, CString y, CInt) { ... } или f = lambda(CInt x, CString y, CInt) { ... }

Т.е. ты предлагаешь ввести новую конструкцию для задания прототипов функций?

> Почему бы не создавать CSymbol просто по наличию "" без $ и :?

Потому, что "..." создаёт объекты класса CString.

> Если then это вызов метода, то как-то надо приписать, что это он, хоть через . хоть через -> хоть через что-то еще.

Дело в том, что у меня "=", "+", "-" тоже являются методами. Запись a.=(5); выглядит странно. Разрешить использовать точку, как синоним пробела?

> Вообще мне никогда не нравились вызовы функций без скобок, они хорошо выглядят только в функциональных языках.

some_object method1: arg1 method2: arg2; - так лучше?

> Как обратиться к функции именно как к объекту в вашем языке? Например как передать функцию как параметр другой функции?

'f = { io outn: "Hello, \{arg}!"; }; 'g = { arg("Hello"); }; g(&f);

> Синонимы лучше не делать - это большое заблуждение, что надо несколько конструкций типа if/unless в руби. Лучше оставлять только один способ выполнить действие, иначе начнется бардак как в перле. С низкоуровневым оператором сложнее. Как вариант можно попробовать все конструкции языка сделать методами.

У меня сейчас как раз все конструкции языка являются методами. Например, методы "=", "then", "else" есть в классе CObject. Можно использовать комментарии, чтобы получать более читаемый условный оператор:

#if (a > 5) then { io <<< "Value is greater, than 5!"; mode = 9; };

> Вот тут я не понял, зачем при объявлении параметров разрешать писать код, куску { create_home_dir then "/home/\{login}" else null } - место в теле функции, но ни как среди объявлений переменных.

Логично.

> Считаю, что не надо загромождать язык лишними конструкциями типа @$:=> - они, в общем-то, не имеют смысла и только ухудшают читаемость. Все написанное - мое ИМХО.

Спасибо.

kmeaw ★★★
() автор топика
Ответ на: комментарий от kmeaw

Нормально, только влияние руби чувствуется :-)
И при таком варианте не очень понятна необходимость ' да ; в общем-то можно опустить. Хотя вам виднее.
Скажите, этот язык нечто вроде курсового проекта или вы хотите его развивать и выводить в пользование?

anonymous
()
Ответ на: комментарий от anonymous

> И при таком варианте не очень понятна необходимость ' да ; в общем-то можно опустить. Хотя вам виднее.

' нужен для ещё и для того, чтобы создавать локальные переменные.

'x = 3;
{
'x = 4;
#{ здесь x равен 4 }
} eval();
#{ а здесь - снова 3 }

; сбрасывает (resets) текущий объект на environment, таким образом компилятор будет искать не метод у текущего объекта, а объект в текущем environment (а если не найдёт, то и в остальных).

> Скажите, этот язык нечто вроде курсового проекта или вы хотите его развивать и выводить в пользование?

Скорее вроде курсового проекта. Просто мне интересно посмотреть, что будет, если минимизировать количество ключевых слов, управляющих конструкций, или иным образом сделать синтаксис более простым. Не думаю, что кому-то будет интересен "ещё один" язык программирования. Единственное, что может быть интересно - это то, что он компилируемый (выдаёт x86 intel asm, хотя несложно сделать поддержку других архитектур). Если интересно: http://tbpl.info/ (хотя ресурс создавался, когда компилятора ещё не было).

kmeaw ★★★
() автор топика
Ответ на: комментарий от kmeaw

Заменить ключевые слова символами препинания - и получится "0 keywords" ?

Может полезнее написать тринслирующий в код бэкенд к PyPy ?

smartly ★★★
()
Ответ на: комментарий от smartly

> Заменить ключевые слова символами препинания - и получится "0 keywords" ?

= - метод объекта CObject

' - сокращение для generate(CSymbol new(...))

:x y z - сокращение для x(y z)

x: y z - сокращение для x(y) z

Остаются только ";" (разделитель выражений) и "," (разделитель аргументов), что сложно назвать ключевыми словами.

> Может полезнее написать тринслирующий в код бэкенд к PyPy ?

PyPy JIT не умеет виртуальные функции.

kmeaw ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.