Можете ли вы написать любой алгоритм без инструкции if?

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

Ответ 1

Smalltalk, который считается "истинно" объектно-ориентированным языком, не имеет оператора "if", и в нем нет инструкции "для", нет инструкции "while". Существуют и другие примеры (например, Haskell), но это хороший вариант.

Цитата Smalltalk не имеет инструкции "if" :

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

Инструкция "if" является мерзостью на объектно-ориентированном языке.

Почему? Ну, язык OO составлен классов, объектов и методов и утверждение "if" неизбежно отсутствует из тех. Вы не можете написать "if" в OO. Он не должен существовать. Условное исполнение, как и все иначе, должен быть метод. Метод что? Boolean.

Теперь, как ни странно, в Smalltalk, Boolean имеет метод, называемый ifTrue: ifFalse: (это имя будет выглядеть теперь довольно странно, но передайте его для Теперь). Его абстракция в булевом, но Boolean имеет два подкласса: True и Ложь. Метод передается двумя блоками кода. В True метод просто запускает код для истинного случая. В False, он запускает код для ложного дело. Вот пример, который, надеюсь объясняет:

(x >= 0) ifTrue: [
'Positive'
] ifFalse: [
'Negative'
]

Вы должны уметь видеть ifTrue: и ifFalse: там. Не волнуйся, что они не вместе.

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

true ifTrue: [
'Positive'
] ifFalse: [
'Negative'
]

Я надеюсь, что это довольно очевидно, что что приведет к "положительному".

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

false ifTrue: [
'Positive'
] ifFalse: [
'Negative'
]

Это производит "Отрицательный".

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

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

Ответ 2

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

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

объяснение причин, по которым полиморфизм:

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

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();
}

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

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

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 типа, которые поддерживают оператор *, что позволяет использовать этот метод с типами, которые еще не созданы.

См. polymorphism, fooobar.com/questions/752/...

>

Ответ 3

Хотя и не связанный с ООП: в Prolog единственный способ записать все ваше приложение без инструкций.

Ответ 4

Угу. Операторы if подразумевают ветки, которые могут быть очень дорогостоящими на многих современных процессорах, особенно PowerPC. Многие современные ПК выполняют много переупорядочивания трубопроводов, и поэтому отклонения от прогноза отрасли могут стоить порядкa > 30 циклов на провал ветки.
При программировании консоли иногда быстрее просто выполнить код и игнорировать его, чем проверить, следует ли его выполнить!

Простой отказ ветвления в C:

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

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

 i = (i + 1) & 15;  

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

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

Ответ 5

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

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

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

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

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

if-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

Обоснование кампании "анти-если" похоже на то, что сказал Кент Бек:

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

Если вы не знаете, как повлиять на программу с составом и наследованием, ваши классы и методы будут со временем увеличиваться. Когда вам нужно внести изменения, проще всего добавить IF где-нибудь. Добавьте слишком много IFs, и ваша программа станет все меньше и меньше поддерживаемой, и все же проще всего будет добавить больше IFs.

Вам не нужно превращать IF в совместное использование объектов; но это очень хорошо, когда вы знаете, как: -)

Ответ 7

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

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 для каждого объекта. В некотором смысле, это именно обратное соответствие шаблонов. "if" полезен, но в некоторых случаях это не лучшее решение.

Ответ 8

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

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

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

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

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

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

Итак, нет, я не думаю, что замена таких утверждений if всегда является улучшением. Это часто, но не всегда.

Ответ 9

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

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

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

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

Используя рекомендации, выдвинутые в кампании anti-if, насколько они рекомендуют, для меня выглядит как программирование "ooh, new shiny thing".

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

Ответ 10

У Haskell даже нет утверждений, являющихся чисто функциональными.; D

Ответ 11

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

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

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

псевдо-Haskell:

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-style if, у них есть другие способы разрешить вам принимать решения.

Ответ 12

Это действительно игра с кодировкой, которую я люблю играть с языками программирования. Он назывался "если бы у нас не было", который имеет свое происхождение: http://wiki.tcl.tk/4821

В принципе, если мы запрещаем использование условных конструкций в языке: no if, no 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')}
);

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

Ответ 13

Вы можете избежать ifs в своем коде бизнес-логики, если будете хранить их в своем строительном коде (фабрики, строители, поставщики и т.д.). Код вашей бизнес-логики будет более читабельным, понятным или более простым в обслуживании или расширении. См.: http://www.youtube.com/watch?v=4F72VULWFvc

Ответ 14

Идея полиморфизма заключается в вызове объекта без предварительной проверки класса этого объекта.
Это не означает, что оператор 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.
}

Ответ 15

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

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

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

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

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

Ответ 16

Хорошо, если вы пишете на Perl, это легко!

Вместо

if (x) {
    # ...
}

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

unless (!x){
    # ... 
}

; -)

Ответ 17

В ответ на вопрос и, как было предложено последним респондентом, вам нужны некоторые операторы if для обнаружения состояния в factory. Затем вы создаете набор взаимодействующих классов, которые решают проблему, специфичную для штата. Конечно, при необходимости потребуются другие условия, но они будут сведены к минимуму.

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

Здесь упоминается интересный smalltalk, как тот язык, который я использовал до того, как его перетащили на Java. Я не возвращаюсь домой, как раньше.

Ответ 18

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

При использовании оператора and, если первый операнд оценивается как false, тогда нет необходимости оценивать второй. С оператором or это противоположно - нет необходимости оценивать второй операнд, если первый true. Некоторые языки всегда ведут себя так, другие предлагают альтернативный синтаксис.

Здесь код if - elseif - else, сделанный в JavaScript, только с использованием операторов и анонимных функций.

document.getElementById("myinput").addEventListener("change", function(e) {

  (e.target.value == 1 && !function() {
    alert('if 1');
  }()) || (e.target.value == 2 && !function() {
    alert('else if 2');
  }()) || (e.target.value == 3 && !function() {
    alert('else if 3');
  }()) || (function() {
    alert('else');
  }());

});
<input type="text" id="myinput" />