Почему большинство языков программирования имеют только операторы сравнения двоичного равенства?

Это невозможно.

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

Пожалуйста, просмотрите эту ссылку для получения дополнительной информации : https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload

window.onbeforeunload = funcRef
  • funcRef является ссылкой на функцию или выражение функции.
  • Функция должна назначить строковое значение для свойства returnValue объекта Event и вернуть ту же строку.

Пример:

window.onbeforeunload = function(e) {
    return 'Dialog text here.';
};
blockquote>

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

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

Событие beforeunload создано таким образом, чтобы защитить пользователей от вредоносных скриптов.

Если разрешено такое управление, кто-то может заблокировать ваш браузер в

Изменить.:

Мне удалось показать диалоговое окно подтверждения, которое работает почти так же, как вы хотите, присоединение к 2 событиям beforeunload и unload. Он работает в Internet Explorer 11, Firefox 40 и Safari 5.1 для Windows (что я могу подтвердить прямо сейчас):

var alreadyTriggered = false;

function onQuit() {
  if (alreadyTriggered) return true;
  alreadyTriggered = true;

  if (confirm('Sure?')) {
    alert('OK');
  } else {
    alert('Cancel');
  }
}

window.onbeforeunload = onQuit;
window.onunload = onQuit;
You can reload the page to test it here.

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

До сих пор нет возможности избежать изменения страницы или закрытия страницы, а также не использовать эту функцию в Chrome. Это также не будет работать в Firefox, событие не было запущено взаимодействием с пользователем.

29
задан Davy8 9 July 2010 в 23:35
поделиться

24 ответа

В Haskell легко определить функцию для этого:

matches x ps = foldl (||) False $  map (\ p -> p x) ps

Эта функция принимает список значений предикатов (типа a -> Bool) и возвращает True, если любой из предикаты соответствуют значению.

Это позволяет вам что-то вроде этого:

isMammal m = m `matches` [(=="Dog"), (=="Cat"), (=="Human")]

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

isAnimal a = a `matches` [isMammal, (=="Fish"), (=="Bird")]
12
ответ дан Zifre 9 July 2010 в 23:35
поделиться

Это может быть воспроизведено в Lua с помощью некоторой мета-магии: D

local function operator(func)
    return setmetatable({},
        {__sub = function(a, _)
            return setmetatable({a},
                {__sub = function(self, b)
                    return f(self[1], b)
                end}
            )
        end}
    )
end


local smartOr = operator(function(a, b)
    for i = 1, #b do
        if a == b[i] then
            return true
        end
    end
    return false
end)


local isPrimaryColor = someColor -smartOr- {"Red", "Blue", "Either"}

Примечание: Вы можете изменить имя -smartOr- на что-то вроде -isEither-, чтобы сделать его еще БОЛЬШЕ читаемым. ]

0
ответ дан warspyking 9 July 2010 в 23:35
поделиться

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

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

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

0
ответ дан Lazarus 9 July 2010 в 23:35
поделиться

Языки на компьютерах сравниваются как двоичные, потому что все они предназначены для машины, которая использует двоичные данные для представления информации. Они были разработаны с использованием схожей логики и с похожими целями. Английский язык не был разработан логически, предназначен для описания алгоритмов, а человеческий мозг (аппаратное обеспечение, на котором он работает) не основан на двоичном коде. Это инструменты, предназначенные для различных задач.

-1
ответ дан Jay 9 July 2010 в 23:35
поделиться

Просто добавить в примеры языков

Схема

(define (isPrimaryColor color)
  (cond ((member color '(red blue yellow)) #t)
        (else #f)))

(define (someNumberTest x)
  (cond ((or (and (>= x 1) (<= x 100)) (and (>= x 10000 (<= x 2000))) #t)
        (else #f)))
0
ответ дан Justin Hamilton 9 July 2010 в 23:35
поделиться

Две возможности

Java

boolean isPrimary = Arrays.asList("red", "blue", "yellow").contains(someColor);

Python

a = 1500
if  1 < a < 10 or  1000 < a < 2000:
     print "In range"
0
ответ дан OscarRyz 9 July 2010 в 23:35
поделиться

Это потому, что языки программирования находятся под влиянием математики, логики и теории множеств в частности. Булева алгебра определяет операторы ∧, ∨ таким образом, что они не работают как разговорный естественный язык. Ваш пример будет записан так:

Let p(x) be unary relation which holds if and only if x is a primary color
p(x) ⇔ r(x) ∨ g(x) ∨ b(x)
or
p(x) ⇔ (x=red) ∨ (x=green) ∨ (x=blue)

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

РЕДАКТИРОВАТЬ: Вышеприведенное утверждение можно упростить, используя обозначение набора:

p(x) ⇔ x ∈ {red, green, blue}

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

type
    color = (red, green, blue, yellow, cyan, magenta, black, white);

function is_primary (x : color) : boolean;
begin
    is_primary := x in [red, green, blue]
end

Но наборы в качестве языковой функции не завоевали популярность.

PS. Извините за мой несовершенный английский.

1
ответ дан el.pescado 9 July 2010 в 23:35
поделиться

Как математик, я бы сказал, что цвет является основным в том и только в том случае, если он является членом набора {красных, зеленых, синих} основных цветов.

И это именно то, что вы могли бы сказать в Delphi:

isPrimary := Colour in [clRed, clGreen, clBlue]

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

const
  LOOPS = [pntRepeat, pntDoWhile, pntFor];

, а затем в несколько строк

if Nodes[x].Type in LOOPS then

Философскую часть вопроса

@supercat, и т.д. («Что касается того, почему никто этого не сделал, я не знаю».):

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

X = Y,

. Но если X может быть одной из множества вещей A, B, C, ..., тогда она определит набор S = {A, B, C, ...} этих вещей и напишет

X ∈ S.

Действительно, это чрезвычайно распространено, что вы (математики) пишете X ∈ S, где S - это множество

S = {x ∈ D; P(x)}

объектов в некоторой вселенной D, обладающих свойством P, вместо записи P(X). Например, вместо того, чтобы сказать «x является положительным действительным числом» или «PositiveReal (x)», можно сказать x ∈ ℝ⁺.

1
ответ дан Andreas Rejbrand 9 July 2010 в 23:35
поделиться

Мне вспоминается, когда я впервые начал изучать программирование на языке Basic, и в какой-то момент я написал

if X=3 OR 4

Я намеревался сделать это так, как вы описываете, если X равен 3 или 4. Компилятор интерпретировал это как:

if (X=3) OR (4)

То есть, если X = 3 верно, или если 4 верно. Так как он определил все ненулевое значение как истинное, 4 - это истина, все ИЛИ ИСТИНА - это истина, и поэтому выражение всегда было истинным. Я потратил много времени на то, чтобы понять это.

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

1
ответ дан Jay 9 July 2010 в 23:35
поделиться

Вопрос обоснованный, и я бы не стал считать это изменение синтаксическим сахаром. Если сравниваемое значение является результатом вычислений, было бы лучше сказать:

  if (someComplicatedExpression ?== 1 : 2 : 3 : 5)

, чем сказать

  int temp;
  temp = someComplicatedExpression;
  if (temp == 1 || temp == 2 || temp == 3 || temp == 5)

, особенно если не было никакой другой необходимости для временной переменной обсуждаемый. Современный компилятор мог бы, вероятно, распознать короткое полезное время жизни «temp» и оптимизировать его для регистра, и, вероятно, мог бы распознать шаблон «посмотрим, является ли переменная одной из определенных констант», но не было бы вреда, если бы программист сохранить компилятор проблемы. Указанный синтаксис не будет компилироваться на любом существующем компиляторе, но я не думаю, что он будет более двусмысленным, чем (a + b >> c + d), чье поведение определено в спецификации языка.

Что касается того, почему никто этого не сделал, я не знаю.

1
ответ дан supercat 9 July 2010 в 23:35
поделиться

Иконка содержит объект, который вы описываете.

if y < (x | 5) then write("y=", y)

Мне скорее нравится этот аспект Icon.

2
ответ дан Paul Nathan 9 July 2010 в 23:35
поделиться

В Perl 6 вы можете сделать это с помощью соединений :

if $color eq 'Red'|'Blue'|'Green' {
    doit()
}

В качестве альтернативы вы можете сделать это с помощью оператора интеллектуального сопоставления (~~). Следующее примерно эквивалентно синтаксису if value in list: в Python, за исключением того, что ~~ делает намного больше в других контекстах.

if ($color ~~ qw/Red Blue Green/) {
    doit()
}

Парены также делают его действительным perl 5 (> = 5.10); в Perl 6 они необязательны.

13
ответ дан Daenyth 9 July 2010 в 23:35
поделиться

Вам понравится Perl 6 , потому что он имеет:

И вы можете комбинировать оба диапазона:

$someNumber ~~ (1..100) | (1000..2000)
5
ответ дан dolmen 9 July 2010 в 23:35
поделиться

В C #:

if ("A".IsIn("A", "B", "C"))
{
}

if (myColor.IsIn(colors))
{
}

Использование этих расширений:

public static class ObjectExtenstions
{
    public static bool IsIn(this object obj, params object [] list)
    {
        foreach (var item in list)
        {
            if (obj == item)
            {
                return true;
            }
        }

        return false;
    }

    public static bool IsIn<T>(this T obj, ICollection<T> list)
    {
        return list.Contains(obj);
    }

    public static bool IsIn<T>(this T obj, IEnumerable<T> list)
    {
        foreach (var item in list)
        {
            if (obj == item)
            {
                return true;
            }
        }

        return false;
    }
}
2
ответ дан John Gietzen 9 July 2010 в 23:35
поделиться

Я думаю, что большинство людей считают что-то вроде

isPrimaryColor = ["Red", "Blue", "Yellow"].contains(someColor)

достаточно ясным, что им не нужен дополнительный синтаксис для этого.

23
ответ дан mqp 9 July 2010 в 23:35
поделиться

Python на самом деле дает вам возможность делать последние вещи довольно хорошо:

4
ответ дан Christian 9 July 2010 в 23:35
поделиться

COBOL использует уровни 88 для реализации именованных значений, именованных групп значений и именованных диапазонов значений.

Например:

01 COLOUR         PIC X(10).
   88 IS-PRIMARY-COLOUR VALUE 'Red', 'Blue', 'Yellow'.
...
MOVE 'Blue' TO COLOUR
IF IS-PRIMARY-COLOUR
   DISPLAY 'This is a primary colour'
END-IF

Тесты на дальность охватываются следующим образом:

01 SOME-NUMBER    PIC S9(4) BINARY.
   88 IS-LESS-THAN-ZERO    VALUE -9999 THRU -1.
   88 IS-ZERO              VALUE ZERO.
   88 IS-GREATER-THAN-ZERO VALUE 1 THRU 9999.
...
MOVE +358 TO SOME-NUMBER
EVALUATE TRUE
    WHEN IS-LESS-THAN-ZERO
         DISPLAY 'Negative Number'
    WHEN IS-ZERO
         DISPLAY 'Zero'
    WHEN IS-GREATER-THAN-ZERO
         DISPLAY 'Positive Number'
    WHEN OTHER
         DISPLAY 'How the heck did this happen!'
END-EVALUATE

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

6
ответ дан NealB 9 July 2010 в 23:35
поделиться
1114 Я полагаю, что языки создаются по привычке. Ранние языки имели бы только операторы двоичного сравнения, потому что их было проще реализовать. Все привыкли говорить (x > 0 and x < y), пока разработчики языка не удосужились поддержать общую форму в математике, (0 < x < y).

В большинстве языков оператор сравнения возвращает логический тип. В случае 0 < x < y, если это интерпретировать как (0 < x) < y, это было бы бессмысленно, поскольку < не имеет смысла сравнивать булевы значения. Следовательно, новый компилятор может интерпретировать 0 < x < y как tmp:=x, 0 < tmp && tmp < y без нарушения обратной совместимости. Однако в случае x == y == z, если переменные уже являются булевыми значениями, неясно, означает ли это x == y && y == z или (x == y) == z.

В C # я использую следующий метод расширения, чтобы вы могли написать someColor.IsOneOf("Red", "Blue", "Yellow"). Это менее эффективно, чем прямое сравнение (как в случае с массивом, циклом, вызовами Equals() и боксом, если T является типом значения), но это, безусловно, удобно.

public static bool IsOneOf<T>(this T value, params T[] set) 
{
    object value2 = value;
    for (int i = 0; i < set.Length; i++)
        if (set[i].Equals(value2))
            return true;
    return false;
}
2
ответ дан Qwertie 9 July 2010 в 23:35
поделиться

Вам придется немного пройти уровень абстракции, чтобы выяснить причину. Инструкции сравнения / перехода в x86 являются двоичными (так как они могут быть легко вычислены за несколько тактов), и так оно и было.

Если хотите, многие языки предлагают абстракцию для этого. В PHP, например, вы можете использовать:

$isPrimaryColor = in_array($someColor, array('Red', 'White', 'Blue'));
1
ответ дан quantumSoup 9 July 2010 в 23:35
поделиться

В Python вы можете сказать ...

isPrimaryColor = someColor in ('Red', 'Blue', 'Yellow')

... который я нахожу более читабельным, чем ваш синтаксис (== "Red" or == "Blue"). Есть несколько причин для добавления поддержки синтаксиса для языковой функции:

  • Эффективность : здесь нет причин, так как нет улучшения скорости.
  • Функциональность : тоже не проблема; в новом синтаксисе вы ничего не можете сделать, чего не можете сделать в старом.
  • Разборчивость : большинство языков прекрасно справляются со случаем, когда вы проверяете равенство нескольких значений. В других случаях (например, someNumber (> 1 and < 10)) это может быть более полезным, но даже тогда это не приносит вам большой выгоды (а Python позволяет вам сказать 1 < someNumber < 10, что еще яснее).

Так что не ясно, предложенные изменения особенно полезны.

2
ответ дан Chris B. 9 July 2010 в 23:35
поделиться

В python вы можете сделать что-то вроде этого:

color = "green"

if color in ["red", "green", "blue"]:
    print 'Yay'

Он называется оператором in , который проверяет членство в наборе.

18
ответ дан miku 9 July 2010 в 23:35
поделиться

Я пока не вижу ответа Objective-C. Вот один из них:

BOOL isPRimaryColour = [[NSSet setWithObjects: @"red", @"green", @"blue", nil] containsObject: someColour];
1
ответ дан JeremyP 9 July 2010 в 23:35
поделиться

Ruby

Содержится в списке:

irb(main):023:0> %w{red green blue}.include? "red"
=> true
irb(main):024:0> %w{red green blue}.include? "black"
=> false

Числовой диапазон:

irb(main):008:0> def is_valid_num(x)
irb(main):009:1>   case x
irb(main):010:2>     when 1..100, 1000..2000 then true
irb(main):011:2>     else false
irb(main):012:2>   end
irb(main):013:1> end
=> nil
irb(main):014:0> is_valid_num(1)
=> true
irb(main):015:0> is_valid_num(100)
=> true
irb(main):016:0> is_valid_num(101)
=> false
irb(main):017:0> is_valid_num(1050)
=> true
9
ответ дан Mark Rushakoff 9 July 2010 в 23:35
поделиться

Пока никто не упомянул SQL. Он имеет то, что вы предлагаете:

SELECT
    employee_id
FROM 
    employee
WHERE
    hire_date BETWEEN '2009-01-01' AND '2010-01-01' -- range of values
    AND employment_type IN ('C', 'S', 'H', 'T')     -- list of values
7
ответ дан Jeffrey L Whitledge 9 July 2010 в 23:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: