Определение функции область определения функции область значения функции: область определения и область значений функций + ПРИМЕРЫ

Функция уже определена в области — Вопрос

Пользователи Скала

Джимка

#1

Я не понимаю сообщение «функция уже определена в области».

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

Может ли кто-нибудь помочь мне понять, когда это разрешено, а когда нет?

В данном случае не допускается.

Впрочем, в данном случае вроде нормально.

ждукер

#2

Хм.

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

(Кроме того, обычная проверка работоспособности: вы действительно пытались его скомпилировать? Никогда не верьте, что IntelliJ прав на 100% в этом вопросе. Это раздражает, но пока LSP не станет основой для всех IDE, вам нужно знать о это.)

Код, как вы показываете, кажется, должен быть в порядке, поэтому я не уверен, что здесь происходит…

jimka

#3

@jducoeur Спасибо за подсказку, да, действительно, неудачный пример включает в себя гораздо больше, поэтому мне нужно выделить лучший неудачный тестовый пример.

Кстати, в этом случае IntelliJ выдает ту же ошибку, что и scalac.

Джимка

#4

@jducoeur Вот урезанная версия, которая, кажется, все еще воспроизводит проблему. Хотя теперь код вообще работает, потому что я убрал всю логику программы.

В этом случае я все еще получаю сбивающее с толку предупреждение/ошибку компилятора о том, что у меня есть несколько определений в области видимости. Я действительно не понимаю, почему иногда это работает, а иногда нет.

gist.github.com
https://gist.github.com/jimka2001/11dd96314687eb0112bba0e023dade9e
Metro-funny-error.scala
 импорт scala.collection.immutable
объект MetroFunnyError {
  val stationPositions = Массив (
    («Настоятельницы», 308, 536),
    («Александр Дюма», 472, 386),
    («Альма Марсо», 193, 404),
    («Алесия», 290, 244),
    («Анатоль Франс», 138, 517),
    ("Анверс", 324, 521), 
Этот файл был усечен. показать оригинал

ждукер

#5

Ладно, посмотрим. Вот полностью свернутый репродуктор, так что мы можем поиграть с этим…

1 Нравится

21 марта 2019 г., 14:37

#6

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

Видимо, это просто известное ограничение, с которым я раньше не сталкивался. Решение, данное по ссылке, является одним из возможных исправлений; другой — просто изменить имя одной из внутренних функций. (Некоторые люди в сообществе FP в целом довольно сильно выступают против перегрузок, но это один из наиболее ярких аргументов, почему это я видел…)

jimka

#7

Хорошо, мне просто нужно переименовать локальную функцию? Поскольку у нас нет типов объединения, есть ли способ переписать функцию в функцию, шаблон которой соответствует ее аргументу? Один шаблон для

Station и один корпус для Option[Station] ?

Кстати, спасибо за помощь. В моем положении такие вопросы действительно озадачивают. А у меня их вроде много. С моей точки зрения, я ничего не пытаюсь перегрузить? Я просто создаю функции с разной специализацией.

wrbriggs1

#8

есть ли еще способ переписать функцию в функцию, шаблон которой соответствует ее аргументу? Один шаблон для Station и один корпус для Option[Station] ?

У кого-то умнее меня может быть творческое решение с использованием системы типов Scala; моя единственная мысль здесь заключается в том, что если вы настроены на другую реализацию для Option и конкретного экземпляра, вы потенциально можете написать каждую как PartialFunction и использовать orElse для их объединения.

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

В вашем примере одна функция просто разворачивает Option, что кажется ненужным — возможно, вы могли бы просто сделать что-то вроде:

 val startupStation = freeVertices.headOption
val routings = startupStation.map(station => firstRoutings(station)) getOrElse Nil
 

Тогда вы можете просто отказаться от функции, которая принимает опцию.

Джимка

#9

wrbriggs1:

o просто придерживаться одного типа параметра, чтобы упростить задачу.

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

ювелир

#10

Джимка:

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

Нет проблем — честно говоря, вы придумали исключительно интересных вопросов для новичка в языке. И ваши инстинкты в значительной степени хороши: вы просто продвигаетесь вперед достаточно быстро, чтобы найти некоторые швы в языке. (В данном случае, тот, о котором я даже не знал…)

тарса

#11

Джимка:

Кстати, спасибо за помощь. В моем положении такие вопросы действительно озадачивают. А у меня их вроде много. С моей точки зрения, я ничего не пытаюсь перегрузить? Я просто создаю функции с разной специализацией.

Перегрузка. См. https://en.wikipedia.org/wiki/Function_overloading

перегрузка функций или перегрузка методов — это возможность создавать несколько функций с одним и тем же именем с разными реализациями

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

Я точно не знаю, что вы имеете в виду под специализацией, но, похоже, это просто частный случай перегрузки.

Вмечем

#12

Я думаю, проблема в том, что сигнатуры функций одинаковы, т. е. f/1. Вы можете попробовать добавить второй параметр в функцию первого уровня с нулевым значением по умолчанию или что-то в этом роде. Это даст вам f/1 и f/2, то есть разные подписи. Но переименование, безусловно, является самым чистым решением.

Джимка

№13

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

Джимка

№14

Спасибо за ссылку на перегружает , я не знал об этой довольно распространенной терминологии; страница википедии, кажется, объясняет это довольно хорошо.

Мне это кажется забавным названием, потому что по-английски перегрузить означает вложить слишком много во что-то. Например, вы перегрузили машину слишком большим количеством багажа. В Лиспе мы называем это специализацией. То есть каждый метод специфицирует свои аргументы таким образом, который отличает его от других методов и влияет на его применимость или порядок специфичности. Мы, вероятно, (в Лиспе) использовали бы перегрузил как уничижительный, означающий, что кто-то добавил слишком много методов к своей полиморфной функции, так что теперь либо производительность, либо удобочитаемость отрицательно сказываются.

Во всяком случае, я нахожу многие концепции в Scala очень похожими на Lisp, но иногда терминология обманчива.

Джимка

№15

производитель:

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

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

Глобальные переменные — зло

Глобальные переменные — зло

Глобальные переменные

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

Локальная переменная — это переменная, определенная внутри функции. Говорят, что такие переменные имеют локальную область видимости.

Функции могут обращаться к глобальным переменным и изменять их.

Изменение глобальных переменных в функции считается плохой практикой программирования. Лучше отправить переменную в качестве параметра (или вернуть ее в операторе return).

Модульное программирование

Думайте о функции как о черном ящике с входами и выходами.

Ввод/вывод функции должен быть полностью определен ее функциональной сигнатурой и возвратом заявление.

сигнатура функции имя функции и список параметров (и возвращаемая спецификация в таких языках, как java), например,

  def pow(x,n) :     # эта строка подпись функции
        total=1
        count = 0
        while count             total=total*x
            count=count+1
        return total # в Java return total # значение также должно быть указано в сигнатуре функции

 # основной
  result = pow(4,2)   # если модульный, мы можем предположить pow-эффекты только результат, без других побочных эффектов
  распечатать результат

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

При модульном программировании нет побочных эффектов , например, глобальных переменные, изменяемые в функции.

Единственным эффектом функции  является возвращаемое значение и модификации параметры списка/объекта (скаляры не могут быть изменены).

Правила области применения Python

Внутри определения функции,

если переменная прочитана , Python проверяет, была ли она определена локально. Если это не так, Python проверит, есть ли глобальная переменная с это имя.

def func():   # прочитать пример
print x  # python будет использовать глобальный x, если он существует

 

если в переменную записывается, для нее создается локальный слот.

def func():  # пример записи
x=7  # глобальный не будет использоваться, даже если глобальный ‘x’ существует.

если вы хотите записать в глобальную переменную, вы должны использовать «глобальную» заявление.

def func():   # как записать глобальную
глобальный х
x=x+1  # изменяет глобальный x

Рассмотрим следующие фрагменты программы. Какой результат?

защита f():

х=10

x=5
f()
печать x

 

 

*************

защита f():

печать х

х = 5
f()

********

защита f():

глобально x
x=10

x=5
f()
печать x

*************

 

защита f():

х=х+1

x=5
f()
печать x

*************

защита f():

list.append(5)

список=[1,2,3,4]
f()
распечатать список

*************

защита f():

список=[]
список.дополнение(5)

список=[1,2,3,4]
f()
распечатать список

*******************

Рабочий лист класса

1. Переписать pow и main так, чтобы они были ЗЛЫМИ, то есть НЕ МОДУЛЬНЫМИ. Просто нарисуй это вне, не программировать его.

2. Какая из следующих функций а) работает правильно, б) использует глобальные переменные немодульным образом

     # 1
    def generateSecret():
        secretCode=[] 
        i=0
        while i<4:
            color = случайный.randint(0,5)
secretCode.append(colors[color])
            i=i+1

    # вызов основной функции
    colors=[‘r’,’b’,’g’,’p’,’y’,’b’]
    generateSecret()
    print secretCode;

    # 2
    def generateSecret():
       
        i=0
        while i<4:
            color = случайный.randint(0,5)
secretCode.append(colors[color])
            i=i+1

    # основной вызов функции:

    colors=[‘r’,’b’,’g’,’p’,’y’,’b’]
    secretCode=[]   
    generateSecret()
    print secretCode

    # 3
    def generateSecret():
        secretCode=[]
        i=0
        while i<4:
            color = случайный.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *