Можно ли записать какой-либо алгоритм без если оператор?

Этот сайт щекотал мое чувство юмора - http://www.antiifcampaign.com/, но полиморфизм может работать в каждом случае, где Вы использовали бы если оператор?

31
задан blank 20 December 2009 в 22:44
поделиться

14 ответов

Smalltalk, который считается "истинно" объектно-ориентированным языком, не имеет оператора "if", и не имеет оператора "for", оператора "while". Есть и другие примеры (например, Хаскелл), но это хороший пример.

Цитируя Smalltalk не имеет утверждения "if":

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

Утверждение "если" является мерзостью в языке, ориентированном на объект.

Почему? Ну, язык ОО состоит классов, объектов и методов, и заявление "если" не может быть неизбежным. из тех. Ты не можешь написать "если" на О, да. Его не должно существовать. Условное исполнение, как и все иначе, это должен быть метод. Метод Что? Булева.

А теперь, как ни странно, в Смоллтоке, У Булева есть метод, называемый ifTrue:ifFalse: (это имя будет выглядеть так. сейчас довольно странно, но передай это для того. Сейчас). В Булеве это абстракция, но... В Булеве есть два подкласса: Правда и Ложь. Метод проходит два блока кода. Правда, метод просто запускает код для истинного случая. На сайте Ложно, он запускает код для ложного... дело. Вот пример, который, будем надеяться. объясняет:

(x >= 0) ifTrue: [
"Положительный
] ifFalse: [
"Отрицательно
]

Вы должны увидеть, если это правда. если Ложь: там. Не волнуйся. они не вместе.

Выражение (x >= 0) оценивает, что правда или ложь. Скажи, что это правда, и тогда мы имеют:

 истинное значение ifTrue: [
"Положительный
] ifFalse: [
"Отрицательно
]

Я надеюсь, что вполне очевидно, что что даст "Положительный".

Если бы это было ложно, мы бы имели:

 ложный ifTrue: [
"Положительно
] ifFalse: [
"Отрицательно
]

Получается "Отрицательно".

Хорошо, вот как это делается. Что такое здорово в этом? Ну, в каком другом язык, ты можешь это сделать? Подробнее Серьёзно, ответ в том, что там в этом нет ничего особенного язык. Все может быть сделано в В стиле "OO", и все делается в OO путь.

Я определенно рекомендую прочитать весь пост и Код - это объект от того же автора.

40
ответ дан 27 November 2019 в 21:26
поделиться

На самом деле это игра в кодирование, в которую я люблю играть с языками программирования. Это называется «если бы у нас не было, если», и берет свое начало здесь: http://wiki.tcl.tk/4821

В основном, если мы запрещаем использование условных конструкций в языке: нет, если, нет while, no for, no if, no switch и т. д. можем ли мы воссоздать нашу собственную функцию IF. Ответ зависит от языка и от того, какие языковые возможности мы можем использовать (помните, что использование обычных условных конструкций обманывает троичные операторы!)

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

proc 0 {true false} {uplevel 1 $false; # execute false code block, ignore true}
proc 1 {true false} {uplevel 1 $true;  # execute true code block, ignore flase}

proc _IF {boolean true false} {
    $boolean $true $false
}

#usage:
_IF [expr {1<2}] {
    puts "this is true"
} {
  #else:
    puts "this is false"
}

или в javascript мы можем злоупотребить свободной типизацией и тем фактом, что почти все может быть преобразовано в строку и сочетать это с ее функциональной природой:

function fail (discard,execute) {execute()}
function pass (execute,discard) {execute()}
var truth_table = {
    'false' : fail,
    'true' : pass
}
function _IF (expr) {
  return truth_table[!!expr];
}

//usage:
_IF(3==2)(
    function(){alert('this is true')},
//else
    function(){alert('this is false')}
);

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

1
ответ дан 27 November 2019 в 21:26
поделиться

answer:**Сайт против использования выражений для **проверки, если объект имеет определенный тип. Это полностью отличается от if (foo == 5). Плохо использовать if как if (foo instanceof pickle). Альтернатива, использующая вместо этого полиморфизм, способствует инкапсуляции, делая код бесконечно простым для отладки, сопровождения и расширения.

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

Объяснение, почему за полиморхистом стоит:

Возьмем эту ситуацию:

void draw(Shape s) {
    if (s instanceof Rectangle)
        //treat s as rectangle
    if (s instanceof Circle)
        //treat s as circle
}

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

void draw(Shape s) {
    s.draw();
}

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

Эта идея сегодня повсюду в программировании, вся концепция интерфейсов - это полиморфизм. (Shape - это интерфейс, определяющий определенное поведение, позволяющий обрабатывать любой тип, реализующий интерфейс Shape в нашем методе). Динамические языки программирования делают это еще глубже, позволяя нам передать в метод любой тип, поддерживающий необходимые действия. Что выглядит лучше для вас: (псевдокод в стиле питона)

def multiply(a,b):
    if (a is string and b is int):
        //repeat a b times.
    if (a is int and b is int):
        //multiply a and b

или используя полиморфизм:

def multiply(a,b):
    return a*b

Теперь можно использовать любые 2 типа, поддерживающие оператор *, что позволяет использовать метод с типами, которые еще не созданы.

Смотрите полиморфизм, что такое полиморфизм на stackoverflow

39
ответ дан 27 November 2019 в 21:26
поделиться

Ну, если ты пишешь на Perl, то это просто!

Вместо

if (x) {
    # ...
}

ты можешь использовать

unless (!x){
    # ... 
}

;-)

.
0
ответ дан 27 November 2019 в 21:26
поделиться

Зависит от языка.

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

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

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

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

.
0
ответ дан 27 November 2019 в 21:26
поделиться

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

if (object.isArray()) {
  // Code to execute when the object is an array.
} else if (object.inString()) {
  // Code to execute if the object is a string.
}
0
ответ дан 27 November 2019 в 21:26
поделиться

Вы можете сделать это без if per se, но вы не можете сделать это без механизма, который позволяет вам принять решение, основанное на каком-то условии.

В сборке нет утверждения if. Существуют условные прыжки.

Например, в Хаскелле нет явного if, вместо того, чтобы многократно определять функцию, я забыл точный синтаксис, но это что-то вроде:

псевдо-хаскелла:

def posNeg(x < 0):
    return "negative"

def posNeg(x == 0):    
    return "zero"

def posNeg(x):
    return "positive"

Когда вы вызываете posNeg(a), интерпретатор посмотрит на значение a, если это < 0, то он выберет первое определение, если это == 0, то он выберет второе определение, в противном случае он выберет третье определение по умолчанию.

Таким образом, в то время как такие языки как Haskell и SmallTalk не имеют обычного утверждения в стиле C , если , они имеют другие средства, позволяющие вам принимать решения.

.
1
ответ дан 27 November 2019 в 21:26
поделиться

Хаскелл даже не имеет, если утверждения, будучи чисто функциональными. ;D

1
ответ дан 27 November 2019 в 21:26
поделиться

Я предполагаю, что вы на самом деле спрашиваете о замене операторов if, которые проверяют типы, в противоположность замене всех операторов if.

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

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

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

if (o instanceof OneType || o instanceof AnotherType) {
    // complicated logic goes here
}

Как бы вы поделились кодом с шаблоном посетителя? Вызвать общий метод? Куда бы вы поместили этот метод?

Так что нет, я не думаю, что замена такого метода, если утверждения всегда являются улучшением. Часто так и есть, но не всегда.

3
ответ дан 27 November 2019 в 21:26
поделиться

Вы можете определить Истину и Ложь объектами (на псевдо-питоне):

class True:
    def if(then,else):
        return then
    def or(a):
        return True()
    def and(a):
        return a
    def not():
        return False()

class False:
    def if(then,else):
        return false
    def or(a):
        return a
    def and(a):
        return False()
    def not():
        return True()

Я думаю, что это элегантный способ построения булеана, и это доказывает, что вы можете заменить каждый if полиморфизмом, но суть анти-иф кампании не в этом. Цель состоит в том, чтобы избежать написания таких вещей, как (в алгоритме поиска пути) :

if type == Block or type == Player:
    # You can't pass through this
else:
    # You can

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

.
3
ответ дан 27 November 2019 в 21:26
поделиться

Да, на самом деле, можно иметь полный язык, который не имеет "if" как таковой и допускает только операторы "while":

http://cseweb.ucsd.edu/classes/fa08/cse200/while.html

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

@ennuikiller: условия были бы просто синтаксическим сахаром:

if (test) body;     is equivalent to    x=test; while (x) {x=nil; body;}

если-then-else немного более многословен:

if (test) ifBody; else elseBody;

is equivalent to

x = test; y = true;
while (x) {x = nil; y = nil; ifBody;}
while (y) {y = nil; elseBody;}

примитивная структура данных - это список списков. можно сказать, что 2 скаляра равны, если это списки одинаковой длины. Вы бы циклически перебирали их одновременно с помощью операторов head/tail и смотрели, останавливаются ли они в одной и той же точке.

Конечно, все это можно обернуть в макросы.

Самый простой полный язык, который можно выучить, это, вероятно, iota. Он содержит только 2 символа ('i' и '*').

.
6
ответ дан 27 November 2019 в 21:26
поделиться

Ага. если утверждения подразумевают ветви, которые могут быть очень дорогостоящими на многих современных процессорах - в частности, PowerPC. Многие современные компьютеры делают много переупорядочивания цепочек, и поэтому ошибочные прогнозы цепочек могут стоить порядка >30 циклов за пропущенную цепочку.
. При консольном программировании иногда быстрее просто выполнить код и проигнорировать его, чем проверить, стоит ли его выполнять!

Простой обход ветки на C:

if (++i >= 15)
{
    i = 0;
)

можно переписать как

 i = (i + 1) & 15;  

Однако, если вы хотите увидеть какую-то реальную анти-if fu, то прочтите это

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

.
6
ответ дан 27 November 2019 в 21:26
поделиться

Хотя и не связанный с ООП: В Прологе единственный способ написать все ваше приложение - без операторов if

.
7
ответ дан 27 November 2019 в 21:26
поделиться

Я часто писал код по рекомендации в анти-if кампании , используя либо обратные вызовы в словаре делегата, либо полиморфизм.

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

Например, F12 (Go To Definition) в визуальной студии приведет вас к абстрактному классу (или, в моем случае, к определению интерфейса).

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

Использование рекомендаций, выдвинутых в анти-if кампании, насколько они выглядят рекомендуемыми, выглядит для меня как программирование "ооо, новая блестящая штука".

Что касается других конструкций, выдвинутых в этой теме, то, хотя это и было сделано в духе веселого вызова, они просто заменяют "если" заявление, и на самом деле не обращают внимания на то, что лежит в основе анти-if кампании.

.
2
ответ дан 27 November 2019 в 21:26
поделиться