LINUX.ORG.RU

Ответ на: комментарий от niemand

Ну вот теперь и понятно, что gradual typing не сделает из Python ничего. Ну максимум C

Зачем всё продолжаешь составлять странные предложения из незнакомых слов? Форум это же не рабочая тетрадка для занятий по русскому языку.

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

Сходил, там 3 месяца назад стали ребрендить MyPy

И? Если что, я уже ответил на это.

Где мифическая compile-time проверка типов??

Как всё запущено...

http://wphomes.soic.indiana.edu/jsiek/what-is-gradual-typing/

«Mypy is an experimental optional static type checker for Python»

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

Ну вот теперь и понятно, что gradual typing не сделает из Python ничего.

Зачем всё продолжаешь составлять странные предложения из незнакомых слов?

Не мешай ему, этот хоть истинное составил. «Нет оснований полагать, что gradual typing сделает из Python ничто.» — так понятнее?

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

Где остальные?

Это в сумме по всем участникам дискуссии

print eval('def:')

А что, вычислять eval он уже в процессе компиляции должен, умник?

необязательная компиляция

И что? Статическая проверка типов ведь тоже необязательная

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

Зачем всё продолжаешь составлять странные предложения из незнакомых слов?

Дорогуша, если тебе какие-то слова из того, что я пишу, не понятны, ты можешь сходить на сайт http://ru.wikipedia.org/ или http://ru.wiktionary.org/ и набрать там любое незнакомое слово

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

Какая разница, что возвратит some_test ()

Ты балбес чтоли? Разница такая, что lal(x) определяется в рантайме в зависимости от результата some_test(). Я русским языком написал, что в первом случае указан хинт int, пусть будет lal(int x), а во втором string, lal(string x). Соответственно, при вызове lal('wow') в первом случае питон должен заругаться, на то что параметр неверного типа. В этом собственно вся мякотка и есть.

no-such-file ★★★★★
()
Ответ на: комментарий от tailgunner

Все еще более запущено. Покажи, где там мифическая compile-time проверка типов? По твоей ссылке compile-time нет, в твоей фразе тоже.

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

Как всё запущенно, вам с машиной надо почитать про русский язык вообще и про двойное отрицание в частности

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

А ты статически типы на этапе исполнения собрался проверять. Ты сам понял, какую муру несешь?

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

Все еще более запущено.

Вижу.

Покажи, где там мифическая compile-time проверка типов?

В слове static и словосочетании statically typed.

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

print eval('def:')

А что, вычислять eval он уже в процессе компиляции должен, умник?

Нет не должен. Но ты на этом настаиваешь, раз пишешь:

Там же есть компиляция в pyc, которая наверняка это словит

Вот тебе ситуация, которую компиляция не словит, даже если она будет. Пример так себе, но и хрень ты тоже так себе спорол.

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

Вот тебе ситуация, которую компиляция не словит, даже если она будет

Ты еще скажи, что Си выдает синтаксические ошибки в рантайме. Ну а чо, компилятор же можно вызвать.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

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

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

Вот тебе ситуация, которую компиляция не словит, даже если она будет.

Просто ты мало понимаешь, о чём говоришь. 'def:' здесь обычная строка. Она не транслируется, это не код. eval не обязан вычисляться на стадии компиляции. Если бы ты просто написал

def:

компилятор бы всё словил как надо

niemand
()
Ответ на: комментарий от no-such-file

Ты балбес чтоли? Разница такая, что lal(x) определяется в рантайме в зависимости от результата some_test(). Я русским языком написал, что в первом случае указан хинт int, пусть будет lal(int x), а во втором string, lal(string x). Соответственно, при вызове lal('wow') в первом случае питон должен заругаться, на то что параметр неверного типа. В этом собственно вся мякотка и есть.

С чего ты взял, что твой пример будет работать в статически типизированном пайтоне? Скорее всего чекер на этапе проверки выведет тебе WARNING о том, что сигнатуры функций не совпадают и принудительно выставит все типы в Any и всё будет работать как будто никаких типов нет.

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

А чего ты хочешь, чтобы я сказал?

Да ничего, вообще ничего — а то лезут тут всякие

Я не очень большой спец по статической типизации и петону

со своим уставом

В том же строго типизированном Common Lisp

в чужой монастырь.

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

В том же строго типизированном Common Lisp * умножает number и проблем с неявным приведением типов нет.

[1]> (* 1 2)
2
[2]> (* 1 2.0)
2.0

Всё также, как и в питоне.

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

проблем с неявным приведением типов нет

А в совсем статически строго типизированном хаскеле и такое бывает:

Prelude> [1.0] ++ [1,2]
[1.0,1.0,2.0]

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

О да, необязательная компиляция ОБЯЗАТЕЛЬНО словит.

Тащемта компиляция в байткод обязательна.

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

Начни с объяснения того, почему при умножении int на float получается именно float.

Потому что это верно с точки зрения математики?

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

Перечитай лучше ещё раз то, что я написал

Цитирую:

Начни с объяснения того, почему при умножении int на float получается именно float

[1]> (type-of 2)
(INTEGER 0 16777215)
[2]> (type-of 1.0)
SINGLE-FLOAT
[3]> (type-of (* 2 1.0))
SINGLE-FLOAT
monk ★★★★★
()
Ответ на: комментарий от monk
>>> import numbers
>>> isinstance(1,numbers.Number)
True
>>> isinstance(2.5,numbers.Number)
True
anonymous
()
Ответ на: комментарий от qnikst

Только тут неявного приведения типов нет

Вообще-то есть. Через [Integer] ++ [Num] и fromInteger получаем [Float]. Причём явно ведь Integer к Float не приводится.

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

Я сказал здесь нету «неявного приведения типов», значит нету.

Через [Integer] ++ [Num] и fromInteger получаем [Float]

Я не знаю ни одного способа как разумным способом интерпретировать эту фразу.

Возможно ты имеешь ввиду что числовые литераты являются переопредлененными и к ним примеряется fromIntegral или fromRational но это не явное или неяыное приведение типа т.к. в программе исходного типа не будет, только конечный, в твоём примере выше создастся список из только Floating a=> a, никаких Integer там не будет. //заставить там быть Rational еще реально, но даже тут неявного приведения нет.

Чтобы продемонстрировать его нужно написать какое-нибудь a `operation` b и где в a и b разные типы, в примере выше тип одинаковый.

А вот что говорит Haskell report

The syntax of numeric literals is given in Section 2.5. An integer literal represents the application of the function fromInteger to the appropriate value of type Integer. Similarly, a floating literal stands for an application of fromRational to a value of type Rational (that is, Ratio Integer). Given the typings: fromInteger :: (Num a) => Integer -> a fromRational :: (Fractional a) => Rational -> a integer and floating literals have the typings (Num a) => a and (Fractional a) => a, respectively. Numeric literals are defined in this indirect way so that they may be interpreted as values of any appropriate numeric type. See Section 4.3.4 for a discussion of overloading ambiguity.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от niemand

2, и 2.0 являются также number

В питоне тоже. Тогда в чём претензия к питону?

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

Я не знаю ни одного способа как разумным способом интерпретировать эту фразу.

Я имею в виду, что аргументы ++ должны иметь одинаковый тип [a]. Изначальный тип [Integer]++[Float]. Далее, Float относится к классу типов Num. В котором определена функция fromInteger (в данном случае с типом Integer -> Float). Это позволяет операции ++ превратить [Integer] в [Float], после этого получаем [Float]++[Float] и вычисляем.

в программе исходного типа не будет, только конечный

Так я про это и говорю. Ввожу [1, 2], а он неявно преобразуется в [1.0, 2.0]. Если явно указать [1, 2] :: Integer (например через let), то будет выдавать ошибку типов как и должен.

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

Дурачок, ты этот комментарий видел? Тебе дать ссылку на описание числовой башни питона? О чем ты споришь?

Раньше в питоне для деления было такое поведение, как ты хочешь, то есть int/int давало int с округлением в меньшую сторону, безо всякого приведения. В итоге исправили, ибо многие плевались. А на «неправильное» умножение почему-то никто не жаловался. В питоне так принято: если удобно, допускается исключение из правил. А компромиссы есть везде.

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

Изначальный тип [Integer]++[Float]

Начиная с этого места ты не прав. Там у тебя Floating a => [a] -> [a] -> [a].

Так я про это и говорю. Ввожу [1, 2], а он неявно преобразуется в [1.0, 2.0].

Неявное преобразование это когда был один тип и в операции перевёлся в другой, тут у тебя нигда Integer-ов не было. Если идти по этому пути до абсурда то во всех языках используется неявное преобразование текст -> тип данных ЯП.

На всякий случай, ты считаешь uint64_t i = 1ULL; приведением типов?

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

ты считаешь uint64_t i = 1ULL; приведением типов

нет. А double i = 1; или char *s = NULL — считаю.

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

Тип такого списка Num a => [a]

То есть зависит от контекста. В контексте <> ++ [Float] станет [Float], а в контексте <> ++ [Word] станет Word. Это и есть неявное приведение типа.

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

Приведение это операция превращения какого-то одного типа в другой делающаяся неявно. Здесь только один тип. Вот например mempty (0 моноида) он тоже зависит от контекста, но никому здравом уме не приходит в голову сказать, что его тип приводится. Код приведения типов на хацкеле я могу попозже написать.

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

Вот тебе неявное приведение:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DefaultSignatures #-}

type family Wider a b where
  Wider a a = a
  Wider Int Double = Double
  Wider Int Integer = Integer
  Wider a b = Wider b a

class Convert a b where
  convert :: a -> b
  default convert :: (Integral a, Num b) => a -> b
  convert = fromIntegral

instance Convert a a where
  convert = id

instance Convert Int Double

(^+) :: (Num (Wider a b), Convert a (Wider a b), Convert b (Wider a b)) => a -> b -> Wider a b 
a ^+ b = convert a + convert b
*Main> (1 :: Int) ^+ (7:: Double)
8.0

с кодом играйся осторожнее, т.к. семейство типов тут рекурсивное.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 2)
Ответ на: комментарий от qnikst

Здесь только один тип.

Литерал [1, 2] — это любой тип, относящийся к классу Num. Там не один тип.

Код приведения типов на хацкеле я могу попозже написать.

Вопрос терминологии. В функции convert ты показываешь приведение типов уже определённых типов. Но литералы прекрасно работают и без неё. 1 + 2.0 и (1 :: Int) ^+ (7:: Double) дают один и тот же результат.

Причём, это неявное приведение иногда имеет неожиданные результаты:

module Test
where
   seconds_in_day = 86400
   ...

$ ghci Test
*Test> seconds_in_day
86400
module Test
where
   seconds_in_day = 86400
   ...
   day_frac x = x / seconds_in_day
   

$ ghci Test
*Test> seconds_in_day
86400.0

Упс. Тип константы поменялся. Причём неявно.

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

Литерал [1, 2] — это любой тип, относящийся к классу Num. Там не один тип.

Вопрос терминологии. В функции convert ты показываешь приведение типов уже определённых типов.

Я по моему в этом треде уже раза 4 явно сказал что именно это и называется приведением типа. И не называю полиморфные фкнкции приведением.

Я не понял зачем ты показал пример с выводом типов и назвал его приведением. Не, я понимаю, что ты константу без дробной части в коде называешь целым и оно по твоему «неявно приводится» к другому типу, но это не так, а как я написал выше.

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

line](Num c, Num a, Fractional b) => (1::a) (+:: c -> c -> c) (2.0:: b) => /из «+» следует, что a = c, b = c/ => (Num c, Fractional c, Num c) => (1 :: c) (+ :: c -> c -> c) (2.0 ::c) => /Num => Fractional/ => Fractional c => (1::c) (+ :: c->c->c) (2.0::c) на этом бы можно было и остановиться, и здесь был только вывод типов, но т.к. ты любишь ghci, то Defaulting rules => (1::Double) (+ :: Double -> Double -> Double) (2.0 :: Double). Таким образом тут нету приведения типов, т.к. у константы нету конкретного типа, а есть обычный их вывод и «тип константы может быть разным в зависимости от контекста».

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

я понимаю, что ты константу без дробной части в коде называешь целым и оно по твоему «неявно приводится» к другому типу, но это не так

Это не так, но оно так выглядит. Собственно, всё это было к тому, что 1 + 2.0 = 3.0 в питоне тоже не является приведением типов (но похоже выглядит).

По Хаскелу спор можем заканчивать, так как с математической точки зрения, разумеется, ты полностью прав. Я всего лишь хотел показать, что спорно выглядящие моменты есть почти везде. И то, что литералы в Хаскеле не имеют типов (а имеют только класс типов) с точки зрения защиты от ошибок скорее зло. Правильное отношение к типам в этом смысле в Аде (и Паскале).

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

Собственно, всё это было к тому, что 1 + 2.0 = 3.0 в питоне тоже не является приведением типов (но похоже выглядит).

а можешь поподробнее обосновать, а то

>>> a = 1
>>> b = 2.0
>>> type(a)
<type 'int'>
>>> type(b)
<type 'float'>
>>> a+b
3.0

выглядит именно как приведение типов...

И то, что литералы в Хаскеле не имеют типов (а имеют только класс типов) с точки зрения защиты от ошибок скорее зло. Правильное отношение к типам в этом смысле в Аде (и Паскале).

ну.. как сказать, для литералов действует вывод типов, со всеми как положительными, так и отрицательными следствиями отсюда, и я не вижу, почему литерал 7, не может быть валидным Int, Word, Integer, Float, Double, Complex. А когда тип уже выбран - то никакого приведения нету и все четко.

В паскале, если мне не изменяет память, типы тоже неявно приводятся и написать a : integer; b : real; writeln(a+b); вполне можно..

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

выглядит именно как приведение типов...

Возможны варианты:

а) подтипы. operator+(number a, number b) -> number c.

б) ad-hoc полиморфизм как в C++. operator+(int, double), operator+(int, int). тело функции выбирается по типам аргументов.

Вообще в языке с динамической типизацией приведение типов и полиморфизм по типам неотличимы при использовании. Со статической типизацией можно определить f(x : Real) : Real, x : Integer и вызвать f(x). Если запустилось, значит приведение типов есть. :-)

В паскале, если мне не изменяет память, типы тоже неявно приводятся

Да. Там целое считается подтипом вещественного.

я не вижу, почему литерал 7, не может быть валидным ..., Float, Double, Complex

Например, потому что представление вещественных и комплексных чисел не такое как целых. Хотя, конечно, это вопрос привычки.

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