Re[3]: Синтаксис объявления переменных
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 05.04.21 18:36
Оценка: 1 (1) +3 :)
Здравствуйте, x-code, Вы писали:

XC>У вас указателей нет. Я проанализировал и понял что основная проблема — наличие всяких звездочек и прочих спецсимволов.


Так опять же никто не заставляет синтаксис для типа указателей делать как в Си. Делайте "ref int" как в ML или Rust'e, волосы будут шелковистыми. "ID1 * ID2;" это проблема вида "суну себе в колесо палку". Кто заставлял-то?
Re: Синтаксис объявления переменных
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 05.04.21 12:54
Оценка: 6 (2) +2
Здравствуйте, x-code, Вы писали:

XC>Современные языки имеют тенденцию ко второму варианту.

XC>Почему? У него есть какое-то фундаментальное преимущество перед первым?

По-моему, фундаментальных никаких нету. Просто в теории типов издавна было "x : T", потом так же было в языках ML семейства еще с 70х годов. А теперь авторы языков наконец открыли учебники/статьи и прониклись.

Кому как больше нравится, предпочтения чаще всего эстетические. К опциональности указания типов это отношения не имеет.
Что мне лично не очень нравится в нотации "тип справа":
x : T = v
выглядит как "х имеет тип (Т = v)". При том, что в некоторых языках вроде Idris "a = b" это вполне осмысленный тип.
И вообще, почему мы пишем T = v, когда имеем в виду x = v?

И еще лишний символ :, код аж на целую букву длиннее.

Когда типы слева, делать с функциями хтонический ужас как у Си никто не заставляет, конечно.

Я на работе занимаюсь созданием ЯП, и когда добавлял туда типы, сделал типы слева. Получилось довольно складно, имхо:
int x = 42
x = 42                   // тип можно и не указывать, он будет выведен
(a,b) => a+b             // лямбда, все типы выводятся
(int a, int b) => a+b    // лямбда с указанием типов аргументов
(a,b) => int: a+b        // лямбда с указанием типа результата
f(int a, int b) => a+b   // определение функции. заметьте, как легко
f(a, b) => int: a+b      //  превращать лямбду в ф-ю и обратно
inc(x) => int: x+1       //
(int) -> int g = inc     // переменная функционального типа, нет проблем его иметь слева
map((#a) -> #b f, [#a] xs) => ... // тут аргумент функ. типа, тоже все ок
Отредактировано 05.04.2021 12:57 D. Mon . Предыдущая версия .
Re: Синтаксис объявления переменных
От: vsb Казахстан  
Дата: 04.04.21 21:54
Оценка: +2 -1
В первом варианте я пишу: User | и мне IDE уже подсказывает имя переменной user. Которое я и выберу, возможно с тем или иным суффиксом или префиксом. Т.к. очень часто имена переменных используют название типа. Во втором случае это уже так не работает.

Ещё один момент: если я не хочу указывать тип, я пишу var someVariable = .... Т.е. я заменяю название типа на var. Ну или на auto, let или другую подобную конструкцию. Это смотрится очень естественно и логично. Во втором варианте приходится писать этот var всегда, хоть я указываю тип, хоть нет. В этом в принципе есть и свои плюсы (все объявления переменных сразу выделяются) и минусы (лишняя писанина).
Re[2]: STLC
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 05.04.21 07:34
Оценка: +3
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, x-code, Вы писали:


XC>>"сначала объект" используется например в Pascal/Go/Rust/Swift/Scala


Q>Главное, что такая нотация используется в математике, например: https://en.wikipedia.org/wiki/Simply_typed_lambda_calculus

Q>Оттуда уже её впитали все остальные языки (кроме Си-подобных).

C это тоже не первый источник, до этого был Algol, а до него Fortran.
В Fortran, похоже, источником явилось то, что писали

DIMENSION A(10,10)

для определения, что переменная — массив, а не скаляр, а дальше когда стали явно задавать типы — сделали по аналогии:

INTEGER XX
INTEGER YY(10,20)
The God is real, unless declared integer.
Re: Синтаксис объявления переменных
От: MaxxK  
Дата: 23.04.21 20:27
Оценка: 8 (2)
Мне кажется, тут стоит посмотреть с позиций эргономики чтения кода. Особенно для языков с длинными и сложными именами типов, типа C++:

да::когда<уже::наконец, этот, тип<закончится>> x = create_some_object();

let x: тут::Неинтересно<Можно, Пропустить<до::ЗнакаРавенства>> = create_some_object();


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


Второй момент, который актуален для TypeScript и Python: типы-суффиксы проще дописать туда, где их ранее не предполагалось:

def function(x, y: Y):
Re: Types are moving to the right
От: Qbit86 Кипр
Дата: 04.04.21 21:21
Оценка: 2 (1) +1
Здравствуйте, x-code, Вы писали:

XC>"сначала объект" используется например в Pascal/Go/Rust/Swift/Scala


И в Kotlin: https://elizarov.medium.com/types-are-moving-to-the-right-22c0ef31dd4a

Глаза у меня добрые, но рубашка — смирительная!
Re: Синтаксис объявления переменных
От: varenikAA  
Дата: 05.04.21 04:19
Оценка: 2 (1) +1
Здравствуйте, x-code, Вы писали:

XC>Современные языки имеют тенденцию ко второму варианту.

XC>Почему? У него есть какое-то фундаментальное преимущество перед первым?
Думаю потому что современные ЯП осознали, что часто можно выполнить вывод типа из контекста.

let s = 42
// val s : int = 42


При этом двоеточие с типом читаю как уточнение типа переменной

let say (name : string) = Console.WriteLine("Hello, " + name)


Далее логически вытекает приведение типов


type Person(name) =
    class
        do printfn "Person name is %s" name
    end

type Worker(name) =
    class
        inherit Person(name)
        do printfn "Worker name is %s" name
    end

let person = Person("Bob")
let worker = Worker("Steve")
let steve = worker :> Person // успешное приведение к предку (вверх). ошибки не будет

try
    let bob = person :?> Worker
    None
with :? System.InvalidCastException as e ->
    printfn $"Ошибка приведение к потомку(вниз) {e.Message}"
    None
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[5]: Синтаксис объявления переменных
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 06.04.21 11:05
Оценка: 1 (1) +1
Здравствуйте, Sharov, Вы писали:

S>Возможности языка, если так можно сделать, то почему бы не сделать?


Если автор языка создает на ровном месте без хороших на то причин суровые неоднозначности в грамматике, а потом героически их преодолевает, то с одной стороны он, конечно, герой, а с другой стороны дурак.
Re: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.21 21:50
Оценка: 72 (1)
Здравствуйте, x-code, Вы писали:

XC>Современные языки имеют тенденцию ко второму варианту.

XC>Почему? У него есть какое-то фундаментальное преимущество перед первым?

1. Все это полная фигн и вкусовщина. Нет никаких современных и не современных языков. Есть просто выбор авторов. Скажем так C#, Java и С++ дадут фору любому "современному" языку по частоте использования. А 9-й Шарп еще и по фичам.

Постоянно пуши и читаю код на трех языках:
Nemerle - x : int
C#      - int x
C++     - int x

Никаких проблем ни с одним из вариантов при восприятии нет. Разве что несколько более ровно методы в Nemerle располагаются, так как имена не "прыгают" из-за разной длинны типов возвращаемого значения. Но в реальности редко когда читаешь именно имена методов. Нашел его с помощью IDE и читаешь уже код.

Реальные отличия языка в семантике, фичах, рантайме.

2. Как по жизни есть три нотации
int x
x : int
x int

Последняя используется, насколько мне известно, только в Go. Так что серьёзно обсуждать ее распространенность нельзя.

XC>Про т.н. "most vexing parse" я знаю, это ошибка дизайна именно С/С++ и она не имеет прямого отношения к тому что тип идет первым, это скорее проблема того что функция начинается не с ключевого слова (func, fn) а с возвращаемого типа. Сложность с синтаксисом указателей на функции тоже с этим связана.


Как бы отсутствие оной проблемы в C# и Java опровергает твое утверждение про префикс. Это чисто проблема неоднозначности грамматики C.

XC>Все-же интересно, какие преимущества и недостатки есть у обоих способов объявления?


Да никаких. Чистая вкусовщина.

За x : int в Nemerle можно привести в качестве аргумент следующее. В Nemerle конструкция "expression : Type" более универсальна. Ее можно использовать в коде для уточнения типа в любом месте. Скажем вместо такого объявления переменной:
def x : object = expression;

Можно написать:
def x = expression : object;

Во втором случае это будет уточнение типа выражения, а тип переменной будет выведен из выражения.
По сути ":" — это просто оператор языка, который по совместительству используется для задания типа параметров и функций.

Что касается описания "указателей на функцию" — это, по сути, низкоуровневый бред. В "современных" языках программирования используется концепция функционального типа. В Nemerle (как и во многих функциональных языках) их вообще не нужно объявлять. Они описываются как любой другой тип. Например, функциональный тип из целого в строку:
int -> string

или из двух строк в void
string * string -> void

Скажем если наш метод (функция) хочет принять указатель на функцию функцию преобразующую число в строку, то мы можем описать параметр следующим образом:
public MyFunc(value : int, func : int -> string) : string
{
   "Результат: " + func(value)
}


Если нам понадобится именованный тип, то для этого есть конструкция:
type Псевдоним = Тип;

Скажем, если мы захотим получить тип для функции преобразования числа в строку, то можно написать такой псевдоним:
public type IntToStringType = int -> string;

Теперь можно переписать MyFunc с его помощью:
public MyFunc(value : int, func : IntToStringType) : string
{
   "Результат: " + func(value)
}


Такой подход будет работать и в языках использующих тип спереди (int x):
public string MyFunc(int value, int -> string func)
{
   return "Результат: " + func(value);
}

Как видишь никаких неоднозначностей.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 09.04.2021 21:49 VladD2 . Предыдущая версия . Еще …
Отредактировано 09.04.2021 21:43 VladD2 . Предыдущая версия .
Отредактировано 08.04.2021 22:20 VladD2 . Предыдущая версия .
Re[3]: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.21 22:13
Оценка: 4 (1)
Здравствуйте, Sharov, Вы писали:

S>Не очень в теме, но какая разница для парсера x int или int x? В каком-то случае правила сложнее?


Рядом же описали. Разница появляется когда добавляется "*". X * Y может быть как объявлением указателя, так и умножением. А компиляторы так устроены, что им нужно это при разборе выражений. С/С++ опираются на знание того чем является X. Если тип, то будет объявление переменной. Если нет, то умножением. Это делает парсер и лексер контекстно-зависимыми, что сильно их усложняет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Синтаксис объявления переменных
От: torvic Голландия  
Дата: 04.04.21 21:19
Оценка: 2 (1)
Здравствуйте, x-code, Вы писали:

Одерски выбирал, потому что по его мнению имя важней типа и то что хорошо работало в си с короткими именами типов, спрячет его в скале за развесистой декларацией типа
Re: Синтаксис объявления переменных
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 04.04.21 21:23
Оценка: +1
Здравствуйте, x-code, Вы писали:

XC>Современные языки имеют тенденцию ко второму варианту.

XC>Почему? У него есть какое-то фундаментальное преимущество перед первым?

Да. Достаточно попытаться распарсить какой-нибудь int *(*fp)(float*[]) и описать, как это делается (выворачивать в уме все эти конструкции наизнанку).
Да даже typedef int *pint; реально надо прочитать как "pint = type pointer to int" и только после этого начинается понимание (даже если это в простом случае делается тривиально).
Это общее место учебников по C/C++ — при парсинге разворачиваешь эти описания задом наперёд.

XC>Про т.н. "most vexing parse" я знаю, это ошибка дизайна именно С/С++ и она не имеет прямого отношения к тому что тип идет первым, это скорее проблема того что функция начинается не с ключевого слова (func, fn) а с возвращаемого типа.


Совсем прямого — не имеет. Непрямое — имеет — что из-за кривого порядка var int x становятся неадекватными.

XC> Сложность с синтаксисом указателей на функции тоже с этим связана.


Именно с этим.
The God is real, unless declared integer.
Re[3]: Синтаксис объявления переменных
От: vsb Казахстан  
Дата: 04.04.21 21:56
Оценка: +1
Здравствуйте, x-code, Вы писали:

T>>Одерски выбирал, потому что по его мнению имя важней типа и то что хорошо работало в си с короткими именами типов, спрячет его в скале за развесистой декларацией типа


XC>А насколько удобен синтаксис конструкторов с такой нотацией? Я не знаю Scala, но вот допустим на обычном си-подобном языке

XC>
Foo obj(1,2,"hello")
;

XC>или
XC>
Foo obj = new Foo(1,2,"hello")
;


XC>если всё это развернуть, то что получится?

XC>
obj(1,2,"hello") Foo;
или как-то так?


val obj1: Foo = new Foo(1, 2, "hello");
val obj2 = new Foo(1, 2, "hello"); // с автовыводом типа
Re: Синтаксис объявления переменных
От: varenikAA  
Дата: 05.04.21 04:21
Оценка: :)
Здравствуйте, x-code, Вы писали:


XC>
x int;


без двоеточия перед типом
даже хуже читается чем
XC>
int x;


Идеально:
name : string
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[3]: Синтаксис объявления переменных
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 05.04.21 07:29
Оценка: +1
Здравствуйте, x-code, Вы писали:

N>>Да. Достаточно попытаться распарсить какой-нибудь int *(*fp)(float*[]) и описать, как это делается (выворачивать в уме все эти конструкции наизнанку).


XC>Это имеет отношение к тому что тип вначале? Или это следствие того что для функции нет ключевого слова?

XC>
 (func(float*[]) int*)* fp;


Имеет к тому, что тип вначале.
Нет, не следствие.

N>>Да даже typedef int *pint; реально надо прочитать как "pint = type pointer to int" и только после этого начинается понимание (даже если это в простом случае делается тривиально).


XC>typedef вообще отдельная конструкция.


Она следует общему тренду языка. Если бы у него был тип справа, то было бы как во втором примере.

XC>в С++ ввели using, правда странный синтаксис указателей на функции оставили, причем он еще и отличается от того что в typedef

XC>
typedef float (*func_ptr)(int);
XC>using func_ptr = float (*)(int);


Это следствие того, что не смогли исправить до конца.

N>>Совсем прямого — не имеет. Непрямое — имеет — что из-за кривого порядка var int x становятся неадекватными.


XC>Вот тут непонятно, что за "var int x"?


Это если ты потребуешь добавлять var или func, но не сдвинешь тип вправо от переменной.
The God is real, unless declared integer.
Re[2]: Синтаксис объявления переменных
От: x-code  
Дата: 05.04.21 17:56
Оценка: +1
Здравствуйте, D. Mon, Вы писали:

DM>Я на работе занимаюсь созданием ЯП, и когда добавлял туда типы, сделал типы слева. Получилось довольно складно, имхо:


У вас указателей нет. Я проанализировал и понял что основная проблема — наличие всяких звездочек и прочих спецсимволов.

Вот например код вида
ID1 * ID2;

это что? Это может быть и объявление типа
int * ptr;

и умножение двух чисел или объектов с перегруженным оператором
x * y;

И компилятору (а также среде разработки для быстрой подсветки синтаксиса и прочих сервисных вещей) нужно правильно распарсить этот код. Желательно не обращаясь ни к каким таблицам имен и и другим результатам компиляции предыдущего кода — просто по факту того, что такой код есть, однозначно понять что это такое.

Мне тоже нравится когда тип слева, но с другой стороны я прекрасно понимаю аргументы высказавшихся здесь в пользу типа справа. Просто хочется более систематического изложения всех этих аргументов, с подробным рассмотрением всех случаев.
Re: Синтаксис объявления переменных
От: maxkar  
Дата: 06.04.21 15:17
Оценка: -1
Здравствуйте, x-code, Вы писали:

XC>Современные языки имеют тенденцию ко второму варианту.

XC>Почему? У него есть какое-то фундаментальное преимущество перед первым?

Добавлю еще две причины к тому, что уже сказали.

Каррирование функций

Здесь хорошо видны корни ML-семейства, в котором все функции были каррироваными (т.е. от одного аргумента).
let magic a b c = a *. float_of_int (String.length b + c);;                   
magic 1.0 "test" 2;;

Здесь a — float, b — string, c — int. Вопрос — какой тип у magic? И здесь более естественно иметь float -> string -> int -> float вместо float <- int <- string <- float. С первым еще и удобно работать. Например, если применить magic к одному аргументу, получится (string -> int -> float). Можно и справа откусывать, но зачем?

Примерно то же мы имеем в Scala (и прочих функциональных языках):
scala> def magic(a: Float, b: String, c: Int): Float =
     |   a * (b.length() + c)
magic: (a: Float, b: String, c: Int)Float

scala> :t  (magic _)
(Float, String, Int) => Float

scala> :t (magic _).curried
Float => (String => (Int => Float))

Пример — это я из scala console скопировал вывод. Скобочки в последней строке можно при написании опустить, будет то же самое. Иметь тип справа удобно, не пришлось порядок менять.

Обобщенные функции

Я не видел ни одного хорошего решения для указания типов-параметров в языках с типами слева. Java:
class Test<A> {
  <B> B magic(A a, B b) {
    return b;
  }

  public static void main(String[]  args) {
    final Test<String> test = new Test<>();
    test.<Thread>magic(null, null);
  }
}

В классе параметры-типы идут после имени. В методе — до. В вызове метода параметры передаются перед названием метода. Еще лучше это выглядит с обобщенными (generic) конструкторами (ради справедливости, scala вообще не поддерживает обобщенные конструкторы):
class Genc<A> {
  <B> Genc(A a, B b) {
  }

  public static void main(String[] args) {
    new <Integer>Genc<String>("Hello", 42);
  }
}

Удачи такое читать

Ладно, Дарт:
class Test<A> {
  B magic<B>(B b) {
    return b;
  }
}

void main() {
  Test<String> s = new Test<String>();
  s.magic<BigInt>(null);
}

Уже лучше. Но в определении функции ссылка на тип-параметр используется до объявления параметра. И вроде бы мелочи, но ведь не логично:
class Test<A> {
  A magic<A>(A b) {
    return b;
  }
}

void main() {
  Test<String> s = new Test<String>();
  s.magic<BigInt>(BigInt.parse("123"));
}

Что это за приколы с lexical scope? По структуре программы magic вроде возвращает A уровня класса (внешний lexical scope). А по факту — A уровня метода. Сравните эти ужасы со scala:
class Test[A] {
  def magic[B](a: A, b: B): B = b
}

val t = new Test[Int]
t.magic[String](42, "Hi")

Порядок параметров в определении и вызове совпадают. Параметр типа определяется до его использования в определении метода. Плюс в теории типов удобно рассматривать типы как отдельную группу аргументов. Т.е. magic могла бы иметь тип вроде [_:B] => (A, B) => B. Но не имеет, потому что generic functions слишком быстро приводят к проблеме неразрешимости типов. Я плохо помню, что там конкретно становится невозможно проверить. Вроде бы уже простую эквивалентность двух типов вывести нельзя если есть generic function type.
Re[2]: Синтаксис объявления переменных
От: x-code  
Дата: 06.04.21 20:58
Оценка: +1
Здравствуйте, maxkar, Вы писали:

M>

Каррирование функций

M>
scala>> def magic(a: Float, b: String, c: Int): Float =
M>     |   a * (b.length() + c)
M>magic: (a: Float, b: String, c: Int)Float

scala>> :t  (magic _)
M>(Float, String, Int) => Float

scala>> :t (magic _).curried
M>Float => (String => (Int => Float))
M>


А при чем тут тип слева/справа? Вот вариант на некотором псеводкоде с типом слева
def magic(Float a, String b, Int c): Float =  a * (b.length() + c)

Каррирование как было так и остается, порядок типов тот же.

M>

Обобщенные функции

M>Я не видел ни одного хорошего решения для указания типов-параметров в языках с типами слева. Java:

Я понял, вы кажется рассказываете про возвращемый тип слева/справа от списка аргументов функции, а вопрос был про тип слева/справа при объявлении переменных. То что возвращаемый тип функции лучше писать именно справа от списка аргументов — достаточно очевидно, но какое это имеет отношение к типу слева или справа при объявлении переменных?

M>
M>class Test<A> {
M>  <B> B magic(A a, B b) {
M>    return b;
M>  }

M>  public static void main(String[]  args) {
M>    final Test<String> test = new Test<>();
M>    test.<Thread>magic(null, null);
M>  }
M>}
M>


Очевидно что этот синтаксис кривой. Вот вариант на некотором псеводкоде, выглядящий гораздо более понятно и унифицированно:
class Test<A> {
  func<B> magic(A a, B b) B {
    return b;
  }
}


Добавление ключевого слова func или fn для функций по аналогии с class и подобными словами (struct, union, enum...) значительно упрощает синтаксис функций. Но является ли такая аналогия полностью верной для переменных (начинать все с ключевых слов — auto, var, val, let...)?
Синтаксис объявления переменных
От: x-code  
Дата: 04.04.21 21:06
Оценка:
Существует два распространенных варианта синтаксиса
"сначала тип" используется например в C/C++/Java/C#/D
int x;

и "сначала объект" используется например в Pascal/Go/Rust/Swift/Scala (с разными вариациями — двоеточия перед типом и т.п., еще важный момент — часто используются ключевые слова в начале, вроде var и let)
x int;


Современные языки имеют тенденцию ко второму варианту.
Почему? У него есть какое-то фундаментальное преимущество перед первым?

Про т.н. "most vexing parse" я знаю, это ошибка дизайна именно С/С++ и она не имеет прямого отношения к тому что тип идет первым, это скорее проблема того что функция начинается не с ключевого слова (func, fn) а с возвращаемого типа. Сложность с синтаксисом указателей на функции тоже с этим связана.

Все-же интересно, какие преимущества и недостатки есть у обоих способов объявления?
Re: Синтаксис объявления переменных
От: Pzz Россия https://github.com/alexpevzner
Дата: 04.04.21 21:17
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Все-же интересно, какие преимущества и недостатки есть у обоих способов объявления?


Мне как-то попадалось объяснение, почему в Go сделано по второму варианту. Не сути, не ссылки я не помню, поищи сам.

Если учесть, что Go и C сделали примерно одни и те же люди, то их взгляд на вещи имеет значение.
Re[2]: Синтаксис объявления переменных
От: x-code  
Дата: 04.04.21 21:27
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Мне как-то попадалось объяснение, почему в Go сделано по второму варианту. Не сути, не ссылки я не помню, поищи сам.

Pzz>Если учесть, что Go и C сделали примерно одни и те же люди, то их взгляд на вещи имеет значение.

https://blog.golang.org/declaration-syntax
Там в основном упор на сложность объявления типов указателей на функции. Это правда, но это решается введением ключевого слова для функций и никакого отношения не имеет к тому, что в начале при объявлении — тип или объект.
Re: STLC
От: Qbit86 Кипр
Дата: 04.04.21 21:43
Оценка:
Здравствуйте, x-code, Вы писали:

XC>"сначала объект" используется например в Pascal/Go/Rust/Swift/Scala


Главное, что такая нотация используется в математике, например: https://en.wikipedia.org/wiki/Simply_typed_lambda_calculus
Оттуда уже её впитали все остальные языки (кроме Си-подобных).
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Синтаксис объявления переменных
От: x-code  
Дата: 04.04.21 21:44
Оценка:
Здравствуйте, netch80, Вы писали:

N>Да. Достаточно попытаться распарсить какой-нибудь int *(*fp)(float*[]) и описать, как это делается (выворачивать в уме все эти конструкции наизнанку).


Это имеет отношение к тому что тип вначале? Или это следствие того что для функции нет ключевого слова?
 (func(float*[]) int*)* fp;


N>Да даже typedef int *pint; реально надо прочитать как "pint = type pointer to int" и только после этого начинается понимание (даже если это в простом случае делается тривиально).


typedef вообще отдельная конструкция.
в С++ ввели using, правда странный синтаксис указателей на функции оставили, причем он еще и отличается от того что в typedef
typedef float (*func_ptr)(int);
using func_ptr = float (*)(int);


N>Совсем прямого — не имеет. Непрямое — имеет — что из-за кривого порядка var int x становятся неадекватными.


Вот тут непонятно, что за "var int x"?
Re[2]: Синтаксис объявления переменных
От: x-code  
Дата: 04.04.21 21:48
Оценка:
Здравствуйте, torvic, Вы писали:

T>Одерски выбирал, потому что по его мнению имя важней типа и то что хорошо работало в си с короткими именами типов, спрячет его в скале за развесистой декларацией типа


А насколько удобен синтаксис конструкторов с такой нотацией? Я не знаю Scala, но вот допустим на обычном си-подобном языке
Foo obj(1,2,"hello")
;
или
Foo obj = new Foo(1,2,"hello")
;

если всё это развернуть, то что получится?
obj(1,2,"hello") Foo;
или как-то так?
Re: Синтаксис объявления переменных
От: varenikAA  
Дата: 05.04.21 04:24
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Все-же интересно, какие преимущества и недостатки есть у обоих способов объявления?


Источник истины:

(defgeneric description (object)
  (:documentation "Return a description of an object."))

(defmethod description ((object integer))
  (format nil "The integer ~D" object))

(defmethod description ((object float))
  (format nil "The float ~3,3f" object))


Т.е. сначала переменная, потом тип, т.к. тип определяется позже, сначала интерфейс
☭ ✊ В мире нет ничего, кроме движущейся материи.
Отредактировано 05.04.2021 4:25 Разраб . Предыдущая версия .
Re[4]: Синтаксис объявления переменных
От: x-code  
Дата: 05.04.21 08:09
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>
vsb>val obj1: Foo = new Foo(1, 2, "hello");
vsb>val obj2 = new Foo(1, 2, "hello"); // с автовыводом типа
vsb>


А если переменная стековая?
Re[5]: Синтаксис объявления переменных
От: vsb Казахстан  
Дата: 05.04.21 09:00
Оценка:
Здравствуйте, x-code, Вы писали:

vsb>>
vsb>>val obj1: Foo = new Foo(1, 2, "hello");
vsb>>val obj2 = new Foo(1, 2, "hello"); // с автовыводом типа
vsb>>


XC>А если переменная стековая?


В самом языке Scala такого понятия нет. В JVM на стеке могут храниться указатели и примитивные типы, поэтому я думаю, что код вида

var i: Int = 1


таки будет использовать стек, но это уже особенности оптимизации.
Re[5]: Синтаксис объявления переменных
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 05.04.21 09:17
Оценка:
Здравствуйте, x-code, Вы писали:

vsb>>
vsb>>val obj1: Foo = new Foo(1, 2, "hello");
vsb>>val obj2 = new Foo(1, 2, "hello"); // с автовыводом типа
vsb>>


XC>А если переменная стековая?


Escape analysis для ссылочных типов работает в полный рост.
The God is real, unless declared integer.
Re: Синтаксис объявления переменных
От: glh Россия  
Дата: 05.04.21 21:26
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Существует два распространенных варианта синтаксиса

XC>"сначала тип" используется например в C/C++/Java/C#/D
XC>
int x;

XC>и "сначала объект" используется например в Pascal/Go/Rust/Swift/Scala (с разными вариациями — двоеточия перед типом и т.п., еще важный момент — часто используются ключевые слова в начале, вроде var и let)
XC>
x int;


XC>Современные языки имеют тенденцию ко второму варианту.

XC>Почему? У него есть какое-то фундаментальное преимущество перед первым?

XC>Про т.н. "most vexing parse" я знаю, это ошибка дизайна именно С/С++ и она не имеет прямого отношения к тому что тип идет первым, это скорее проблема того что функция начинается не с ключевого слова (func, fn) а с возвращаемого типа. Сложность с синтаксисом указателей на функции тоже с этим связана.


XC>Все-же интересно, какие преимущества и недостатки есть у обоих способов объявления?


Больше связано с устройством компилятора и способом помещения объекта в его таблицах/ветвлениях парсера.
"C"/type first-компиляторы более сложные именно в частности потому, что требуют "возврата".
Успехов!
C уважением, Алексей.
------------------------------------------------
Хороших %s не бывает — бывает не худший вариант.
Re[4]: Синтаксис объявления переменных
От: Sharov Россия  
Дата: 06.04.21 10:10
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM> Кто заставлял-то?


Возможности языка, если так можно сделать, то почему бы не сделать?
Кодом людям нужно помогать!
Re[2]: Синтаксис объявления переменных
От: Sharov Россия  
Дата: 06.04.21 10:12
Оценка:
Здравствуйте, glh, Вы писали:

glh>Больше связано с устройством компилятора и способом помещения объекта в его таблицах/ветвлениях парсера.


Не очень в теме, но какая разница для парсера x int или int x? В каком-то случае правила сложнее?
Кодом людям нужно помогать!
Re[2]: Синтаксис объявления переменных
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 06.04.21 17:23
Оценка:
Здравствуйте, maxkar, Вы писали:

M>Здесь a — float, b — string, c — int. Вопрос — какой тип у magic? И здесь более естественно иметь float -> string -> int -> float вместо float <- int <- string <- float. С первым еще и удобно работать. Например, если применить magic к одному аргументу, получится (string -> int -> float). Можно и справа откусывать, но зачем?


M>Примерно то же мы имеем в Scala (и прочих функциональных языках):

M>
scala> def magic(a: Float, b: String, c: Int): Float =
     |   a * (b.length() + c)
magic: (a: Float, b: String, c: Int)Float

scala> :t  (magic _)
(Float, String, Int) => Float

scala> :t (magic _).curried
Float => (String => (Int => Float))

M>Пример — это я из scala console скопировал вывод. Скобочки в последней строке можно при написании опустить, будет то же самое. Иметь тип справа удобно, не пришлось порядок менять.

Непонятно. Как связан способ записи функционального типа (где порядок типов аргументов соответствует порядку аргументов) и то, с какой стороны от переменной он окажется? Кто мешает тот же самый тип записать слева?
(Float, String, Int) => Float magic = ...


M>

Обобщенные функции

M>Я не видел ни одного хорошего решения для указания типов-параметров в языках с типами слева.

В джаве выглядит странно, да, но вариант из Дарта, Ди или того же С++ вовсе не плох.
Ну используем мы тип-параметр чуть левее, чем он упомянут как параметр, нет в этом ничего крамольного, все равно все на одной строчке.
class Test<A> {
  B magic<B>(B b) {


В некоторых языках типы-параметры и известные типы просто по-разному пишутся, так что специально перечислять их не нужно. В Окамле это 'aaa против bbb, в Хаскеле aaa против Bbb. У меня это #aaa против bbb.


M>Что это за приколы с lexical scope? По структуре программы magic вроде возвращает A уровня класса (внешний lexical scope). А по факту — A уровня метода. Сравните эти ужасы со scala:

class Test[A] {
  def magic[B](a: A, b: B): B = b
}

Чтобы действительно сравнить, попробуй добавить в метод тип-параметр А. Тогда будет аналог дартовского примера, поймем, есть ли похожая проблема или нет.

Но это мы уже про синтаксис объявления методов/функций заговорили, не про переменные (см. заголовок темы).

M>Порядок параметров в определении и вызове совпадают. Параметр типа определяется до его использования в определении метода. Плюс в теории типов удобно рассматривать типы как отдельную группу аргументов. Т.е. magic могла бы иметь тип вроде [_:B] => (A, B) => B. Но не имеет, потому что generic functions слишком быстро приводят к проблеме неразрешимости типов. Я плохо помню, что там конкретно становится невозможно проверить. Вроде бы уже простую эквивалентность двух типов вывести нельзя если есть generic function type.


Ну так то, что в угловых (С++, Дарт и пр.) или квадратных (Скала) скобках идет, это такой список "аргументов" и есть.
Тут самая обычная полиморфная функция, с такими ФЯ работают свободно с середины 70х, никаких проблем там нет. Нужно наворотить хотя бы rank-2 тип, чтобы начались трудности с выводом.
Re: Синтаксис объявления переменных
От: elmal  
Дата: 07.04.21 08:28
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Все-же интересно, какие преимущества и недостатки есть у обоих способов объявления?

Собственно в последнее время статически типизированные языки предпочитают тип выводить из того, что стоит после присваивания, а переменные и константы объявлять как var и val соответственно. Это уже давно пришло и в Java и в C#, собственно как и в плюсы. И вот при таком объявлении ситуация, когда тип все таки желательно указать — в случае если тип справа, то получается более регулярный синтаксис. А если тип слева, то регулярность теряется, в результате читается все то слева, то справа, и читаемость кода ухудшается. Конкретно компиляторам пофиг, от синтаксиса особого усложнения нет, а вот для человека не пофиг.
Re[3]: Синтаксис объявления переменных
От: maxkar  
Дата: 07.04.21 16:32
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Я понял, вы кажется рассказываете про возвращемый тип слева/справа от списка аргументов функции, а вопрос был про тип слева/справа при объявлении переменных. То что возвращаемый тип функции лучше писать именно справа от списка аргументов — достаточно очевидно, но какое это имеет отношение к типу слева или справа при объявлении переменных?


Да, я писал о функциях. Отношение самое прямое — очень удобно, когда типы всех термов (термы — это "имена, обозначающие значения") указываются в одном стиле. Т.е. если у нас тип переменной слева от имени, то и для функции тип (возвращаемый тип) обычно идет слева. Qbit86 даже картинку привел
Автор: Qbit86
Дата: 05.04.21
. Можно, конечно, вразнобой все сделать. Но это будет неестественно:

def magic(Float a, String b, Int c): Float =  a * (b.length() + c)
val (Float, String, Int) => Float magic2 = magic _


Вроде ведь одно и то же объявляется, но какая разница в синтаксисе!

XC>Очевидно что этот синтаксис кривой. Вот вариант на некотором псеводкоде, выглядящий гораздо более понятно и унифицированно:

Не вижу унификации. Почему в определении класса параметры типа идут после имени, а в функции — до? Тогда уж надо

class<A> Test {
  func<B> magic(A a, B b) B {
    return b;
  }
}


XC>Добавление ключевого слова func или fn для функций по аналогии с class и подобными словами (struct, union, enum...) значительно упрощает синтаксис функций. Но является ли такая аналогия полностью верной для переменных (начинать все с ключевых слов — auto, var, val, let...)?


Да! Мне очень нравится такое. Я vim использую, там ключевые слова выделяются. И даже в ide ключевые слова обычно выделяются лучше, чем "C-style" объявление переменной из типа и имени. Плюс все равно есть final/const. Поэтому let/var/val хорошая и очень консистентная замена для "ничего" vs final.
Re[5]: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.21 21:57
Оценка:
Здравствуйте, x-code, Вы писали:

XC>А если переменная стековая?


Без разницы. Это проблемы восприятия С++-ника. В Шарпе new и структуры объявляет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.21 22:03
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>По-моему, фундаментальных никаких нету. Просто в теории типов издавна было "x : T", потом так же было в языках ML семейства еще с 70х годов. А теперь авторы языков наконец открыли учебники/статьи и прониклись.


+1

DM>И вообще, почему мы пишем T = v, когда имеем в виду x = v?


Мы пишем:
(x : T) = v

":" — это такой же оператор как и "=", только приоритеты и ассоциативность разные.

DM>И еще лишний символ :, код аж на целую букву длиннее.


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

А вообще ты странный. Сначала делаешь утвреждение (с которым я согласен), а потом сам начианаешь притягивать за уши что-то чтобы его же и опровергнуть. Ты определить. Или разницы нет. Или она есть.

DM>Когда типы слева, делать с функциями хтонический ужас как у Си никто не заставляет, конечно.


+1
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.21 22:09
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Вот например код вида

XC>
ID1 * ID2;

XC>это что? Это может быть и объявление типа

А зачем для описания указателей использовать тот же оператор, что для умножения?

Это косяк заложенный в язык изначально. В С он обходился тем, что типы заранее известны (предопределены или должны быть заданы тайпдефом). В С++ же это не так. И это создает уже совсем косяк.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.21 22:11
Оценка:
Здравствуйте, glh, Вы писали:

glh>Больше связано с устройством компилятора и способом помещения объекта в его таблицах/ветвлениях парсера.

glh>"C"/type first-компиляторы более сложные именно в частности потому, что требуют "возврата".

Какого еще возврата? Они требуют связи лексера и типизатора, чтобы определять чем является идентификатор.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.21 22:15
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Если автор языка создает на ровном месте без хороших на то причин суровые неоднозначности в грамматике, а потом героически их преодолевает, то с одной стороны он, конечно, герой, а с другой стороны дурак.


В С-и то неоднозначностей не было. Ричи решил, что раз типы хорошо отличимы, на это можно опираться. Неоднозначность ввел Старуструп, когда решил не отказываться от совместимости с С.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Синтаксис объявления переменных
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 09.04.21 02:13
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А вообще ты странный. Сначала делаешь утвреждение (с которым я согласен), а потом сам начианаешь притягивать за уши что-то чтобы его же и опровергнуть. Ты определить. Или разницы нет. Или она есть.


А ты прочитай целиком сообщение-то. Сначала я говорю, что нет фундаментальных преимуществ. А потом перечисляю недостатки.
Re[4]: Синтаксис объявления переменных
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.04.21 21:51
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>А ты прочитай целиком сообщение-то. Сначала я говорю, что нет фундаментальных преимуществ. А потом перечисляю недостатки.


А разве отсутствие недостатков не преимущество? Если у одного подхода есть недостатки, а у другого — нет, значит другой предпочтительнее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Синтаксис объявления переменных
От: alexzzzz  
Дата: 23.04.21 13:04
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>И еще лишний символ :, код аж на целую букву длиннее.


Не просто лишний, но ещё и набирается с шифтом
Re[2]: Синтаксис объявления переменных
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 24.04.21 16:57
Оценка:
Здравствуйте, elmal, Вы писали:

XC>>Все-же интересно, какие преимущества и недостатки есть у обоих способов объявления?

E>Собственно в последнее время статически типизированные языки предпочитают тип выводить из того, что стоит после присваивания, а переменные и константы объявлять как var и val соответственно.

Потыкал палочкой котлин, там как раз var и val. Повбывав бы. Визуально практически не отличимы. Может, конечно, это ни для кого не проблема, только у меня плюсовые комплексы. Но мне было бы гораздо проще код читать, если бы использовалось const, например.

Хотя, если var и val — то из константы переделать в переменную быстрее. Нужно ли оно такое — хз
Маньяк Робокряк колесит по городу
Re[2]: Синтаксис объявления переменных
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 24.04.21 17:05
Оценка:
Здравствуйте, MaxxK, Вы писали:

MK>Мне кажется, тут стоит посмотреть с позиций эргономики чтения кода. Особенно для языков с длинными и сложными именами типов, типа C++:


MK>
MK>да::когда<уже::наконец, этот, тип<закончится>> x = create_some_object();
MK>

MK>
MK>let x: тут::Неинтересно<Можно, Пропустить<до::ЗнакаРавенства>> = create_some_object();
MK>


Есть auto. Довольно удобно.

Правда, иногда, когда много auto, начинаешь забывать, какого типа у тебя в итоге переменная. А если это чужой код, то ещё хуже. Поэтому я авто-ми не особо пользуюсь, хотя в твоём примере auto как раз в тему — тип скорее всего можно понять из имени функции:

[ccode]
auto x = create_some_vector_of_set_of_strings();
MK>[/rust]
Маньяк Робокряк колесит по городу
Re[3]: Синтаксис объявления переменных
От: elmal  
Дата: 24.04.21 17:46
Оценка:
Здравствуйте, Marty, Вы писали:

M>Потыкал палочкой котлин, там как раз var и val. Повбывав бы. Визуально практически не отличимы. Может, конечно, это ни для кого не проблема, только у меня плюсовые комплексы. Но мне было бы гораздо проще код читать, если бы использовалось const, например.

Ну, в Ceylon было сделано поинтереснее, по умолчанию было value то есть неизменяемое, а хочешь переменную — фигачишь variable value. Но var и val не напрягает абсолютно, если ты val сделаешь повторное присваивание — тебе IDE ругнется мгновенно. А по умолчанию давно val юзаю. В kotlin сделали 1 в 1 как в scala, не стали сильно париться, как то проблем из этого никаких не замечал.

А именно в плюсах — наоборот переменная по умолчанию, что несколько противоречит современным практикам, и это уже не исправить.
Re[3]: Синтаксис объявления переменных
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 25.04.21 19:39
Оценка:
Здравствуйте, Marty, Вы писали:

M>Потыкал палочкой котлин, там как раз var и val. Повбывав бы. Визуально практически не отличимы. Может, конечно, это ни для кого не проблема, только у меня плюсовые комплексы. Но мне было бы гораздо проще код читать, если бы использовалось const, например.


Нам-то ещё ничего, а вот китайцам-японцам экзистенциальный ужас — им надо учиться произносить это по-разному. Была куча других вариантов, но выбрали такое...

M>Хотя, если var и val — то из константы переделать в переменную быстрее. Нужно ли оно такое — хз


Сокращение до одного символа менять — точно не нужно
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.