НС>Ты правда думаешь что в какой то момент Language Design Team собирается и думает — то ли ему заняться шарпом, то ли написать еще одну громадную библиотеку?
Да это же Kolesiki, он всегда такой. Его сообщения можно даже по внешнему виду отличать.
Здравствуйте, varenikAA, Вы писали:
AA>Никому не надоело это
Совершенно нет. unless — не нужен ни в одном языке программирования, как раз потому, что он выражается через if. (И те — кто реализовали unless (а это было в прошлом тысячелетии) — уже достаточно насмотрелись на все "преимущества" этой конструкции — и это ясно как божий день — она нахер никому не нужна, по крайней мере в императиве.)
В конструкции unless нет ничего плохого, кроме того, что она плохо совместима с людьми: людям проще думать в позитивной логике.
И запись if(!(...)) и unless(...) — они абсолютно ничем не лучше одна другой, т.к. они одинаково непонятны, но кому? — людям. А компиляторам одинаково пофигу.
Учитесь писать программы — в позитивной логике, везде, где это возможно. Я знаю, это не всегда удобно и не всегда возможно. Но это и не самоцель. Это должно быть так же очевидно, что и создание дополнительной блочной вложенности должно не использоваться — вместо этого, лучше использовать инверсную логику с ранним выходом. Да-да — return из функции/метода. Пуристам ФП, правда, наверное этого не понять, хотя думаю и в том мире это понимают, что чем меньше вложенностей — тем лучше читаемость. Но и это не самоцель. По сути — всё ситуационно. [Конечно, не нужно тут меня тыкать с goto, где можно всё сделать без вложенности, речь же об адекватном и ненужном усложнении на ровном месте. Есть runtime precondition — вы его проверите в любом случае, хотите или нет — проверили, не подходит — на выход (с результатом или без) — это позитивная логика. Это типичный и работающий подход. Это же можно сделать в совсем "позитивной" логике, — проверить предусловия на допустимость, и выполнить работу, а иначе — даже ретурн не надо писать... (вот же ж экономно!) и вот такой подход — на практике — сильно хуже, т.к. смешивает всё вместе окончательно и читается такое — на порядки сложнее, хотя код будет полностью эквивалентный.]
Собственно — по чём плач?
PS: X is not Y — нет, душа не позволяет? А зачем в конструкции X is Y y <<< алиас? И как вы им хотите воспользоваться в unless? Вообще-то это каст с результатом, тупой компилятор его и сделает и поместит на стэке результат. А вы... а вы проверяете, вводите алиас, и отвергаете это всё одним махом. Оно даже на бумаге выглядит бессмысслицей. Определитесь уже, что вы хотите. Я уверен, любая задача вписывается в if/match, а тем более такой примитивный кейс как в вопросе, где выбрасывание ненужностей — несёт просто благо, как раз тупым переписыванием в позитивный матч. [И не надо уповать на оптимизатор, оптимизатор не оптимизируют исходный код — люди которые будут читать эту ахинею в виде unless(X is Y y) должны будут волосы рвать и думать куда там этот y поедет, в какой такой скоуп?!
Здравствуйте, Mystic Artifact, Вы писали: MA> Собственно — по чём плач?
В часто встречающейся ошибке, тут надо еще обязательность скобок по хорошему.
if (cond)
IfTrue();
IfFalse(); // <= выполнится когда не должно
вот лисп гораздо гибче, но когда пишешь if то там четко два блока. и один в when.
я бы сказал дурная гибкость.
if без else размывает смысл.
when четко говорит о намерении. unless можно и не вводить. MA> PS: X is not Y — нет, душа не позволяет?
пропустил, если честно. ну и это только в core. взял на заметку.
MA> А зачем в конструкции X is Y y <<< алиас? MA> И как вы им хотите воспользоваться в unless?
кодстайл такой в конторе. чтобы меньше ветвлений было в коде.
Person p = null; //new();if (p is not Person x) return;//<= C# 9if(!(p is Person x)) return; // <= C# 8
x.Hello();
Здравствуйте, varenikAA, Вы писали: AA>Никому не надоело это ...
`If` — не ооп, сОлид, энтерпрайз, C# вей.
Добавим немного ООП и `if` превращается в темплейм метод, стратегию или в спецификацию
if ...
namespace ConsoleApp2.If
{
public class DTO { public int Value; }
public class X { }
public class Y : X { }
class Foo
{
public void Bar(X x, DTO dto)
{
if (!(x is Y y))
{
Console.WriteLine($"x is not y {dto.Value + 100}");
}
else
{
Console.WriteLine($"x is y {dto.Value - 100}");
}
}
}
public class Program
{
public void Main()
{
X x = new();
Foo foo = new();
foo.Bar(x, new DTO { Value = 100500 });
}
}
}
template method
namespace ConsoleApp.TemplateMethod
{
public class DTO { public int Value; }
public class X { }
public class Y : X { }
abstract class Foo { public abstract void Bar(X x, DTO dto); }
class FooX : Foo { public override void Bar(X x, DTO dto) => Console.WriteLine($"x is not y {dto.Value + 100}"); }
class FooY : Foo { public override void Bar(X x, DTO dto) => Console.WriteLine($"x is y {dto.Value - 100}"); }
public class Program
{
public static void Main()
{
X x = new();
Foo foo = new FooX();
foo.Bar(x, new DTO { Value = 100500 });
}
}
}
strategy
namespace ConsoleApp.Strategy
{
public class DTO { public int Value; }
public class X { }
public class Y : X { }
public interface IFooStrategy<T> where T : DTO { void BarImpl(DTO dto); }
public class Foo<Processor> where Processor : IFooStrategy<DTO>, new()
{
private Processor pr;
public Foo() { this.pr = new Processor(); }
public void Bar(DTO dto) { pr.BarImpl(dto); }
}
class FooXStategy : IFooStrategy<DTO> { public void BarImpl(DTO dto) => Console.WriteLine($"x is not y {dto.Value + 100}"); }
class FooYStategy : IFooStrategy<DTO> { public void BarImpl(DTO dto) => Console.WriteLine($"x is y {dto.Value - 100}"); }
public class Program
{
public static void Main()
{
Foo<FooXStategy> foo = new();
foo.Bar(new DTO { Value = 100500 });
}
}
}
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, vaa, Вы писали:
vaa>В часто встречающейся ошибке, тут надо еще обязательность скобок по хорошему. vaa>вот лисп гораздо гибче, но когда пишешь if то там четко два блока. и один в when. vaa>я бы сказал дурная гибкость.
Это не дурная гибкость — это вкусовщина, как раз, определяющеяся код-стайлом, и его пониманием.
Все правила они по большому счёту свод рекомендаций. Некоторые из них можно энфорсить, некоторые можно записать, но следовать им можно только с пониманием сути правила, которая часто — вообще не донесена.
С другой стороны — вкусы — это такая штука, что они сильнее любого здравомыслящего подхода.
vaa>if без else размывает смысл.
Есть тысяча и одна ситуация кода есть no-throw метод, который обязан делать такое:
if (!precondition) return;
// body
Это справедливо для любого императивного кода. Прекондишн — он вообще может быть что-то вроде Environment.HasShutdownStarted в теле финализатора, потому, что в некоторых случаях можно нажить много охеренных проблем, попытавшись что-то выполнить, когда мы и так пошли закрываться. Я к тому, что прекондишны — они могут даже не принадлежать внутреннему состоянию объекта.
vaa>when четко говорит о намерении. unless можно и не вводить. MA>> PS: X is not Y — нет, душа не позволяет? vaa>пропустил, если честно. ну и это только в core. взял на заметку.
Версия C# зависит только от версии SDK. С некоторыми ограничениями, C# 10, например, можно (и нужно) использовать даже на .NET 4.6. Иногда надо атрибутов досыпать, но в любом случае, при желании — можно без проблем.
А так — я очень давно юзал Nemerle — и все эти похожии конструкции — казались тогда вполне уместными. Но там и совсем другие правила игры. Там ведь не нужно писать return.
MA>> А зачем в конструкции X is Y y <<< алиас? MA>> И как вы им хотите воспользоваться в unless? vaa>кодстайл такой в конторе. чтобы меньше ветвлений было в коде.
Я лично с таким стилем согласен. Вопрос как и когда его использовать. Я не видел стиля который бы чётко объяснил, когда можно не писать сбоки, кроме как соображением, что тело условия влезает в одну строку, и оно не вызывает каких-то странных побочных эффектов.
vaa>
vaa>Person p = null; //new();
vaa>if (p is not Person x) return;//<= C# 9
vaa>if(!(p is Person x)) return; // <= C# 8
vaa>x.Hello();
vaa>
На мой скромный взгляд, тут то как раз и должен быть использован
if (p is Person x) { x.Hello(); }
, просто потому, что результат матча долежн быть доступен, как его результат (понятно, что компилятор умный, но так — понятнее, и держим две вещи рядом).
Если есть цепочки из if->return, — то они должны более-менее легко между собой переставляться без особых последствий (кроме прямых зависимостей между ними).
А подобный инверсный код, скорее всего совсем не такой.
Ну и потом, это же зависит от кода: это ручной сериализатор? Сама то конструкция — простой рантайм диспатч —
if (p is Person x) DispatchPerson(x);
. В маленьких примерах это будет выглядеть ненужным, — но как только под иф закрадётся 10 параметров — уж точно захочется работать с ними так, что все они готовые, таким образом избавившись от проверок (не совсем, но это тоже, в некотором смысле, в некотором сферо-коде — понятнее, хотя где-то напротив — я предпочитаю лапшу из if-else if, у которых внутри не более чем 2-5 строк в каждом). Кажется я только что сам не понял что написал... Короче, если есть рантайм-диспатч — то там по моему должна быть лапша if-else if, а в ней то уж, как бы, кроме как писать прямо — врядли выйдет.
Проблема выразительности — она реально существует. Но, опять же, на мой личный взгляд — чаще всего — это проблема не код-стайла, а конкретного кода, и возможно неадекватного стайла и т.п.
В общем — финальный поинт — может просто нужен метод: ProcessPerson, а в методе-диспетчере — тогда и не надо будет бороться с вложенностью? Ну — это чисто телепатия с моей стороны.
J>namespace ConsoleApp.Strategy J>{ J> public class DTO { public int Value; }
J> public class X { }
J> public class Y : X { }
J> public interface IFooStrategy<T> where T : DTO { void BarImpl(DTO dto); }
J> public class Foo<Processor> where Processor : IFooStrategy<DTO>, new() J> { J> private Processor pr;
J> public Foo() { this.pr = new Processor(); }
J> public void Bar(DTO dto) { pr.BarImpl(dto); } J> }
J> class FooXStategy : IFooStrategy<DTO> { public void BarImpl(DTO dto) => Console.WriteLine($"x is not y {dto.Value + 100}"); }
J> class FooYStategy : IFooStrategy<DTO> { public void BarImpl(DTO dto) => Console.WriteLine($"x is y {dto.Value — 100}"); }
J> public class Program J> { J> public static void Main() J> { J> Foo<FooXStategy> foo = new();
J> foo.Bar(new DTO { Value = 100500 }); J> } J> } J>}
Что-то я не понял, зачем тут class X и class Y.
А вообще это всё крепко, но олдскульно. Молодёжно будет так.
using System;
dynamic obj = new X();
Worker. DoWork(obj);
obj = new Y();
Worker.DoWork(obj);
class X { }
class Y : X { }
static class Worker {
public static void DoWork(X x)
{
Console.WriteLine(nameof(X));
}
public static void DoWork(Y y)
{
Console.WriteLine(nameof(Y));
}
}
Здравствуйте, varenikAA, Вы писали:
AA>Ну дайте уже AA>unless(X is Y y)
Вот скажу честно, что без unless легко переживаю. Более того, unless путает. Все же мозг привык к if/when, т.е. прямой логике и иногда замена unless на if/when вносит случайные ошибки.
А вот foreach немерловый на фононе убожества из C# просто мега-крут!
Ну, и по любому лучше иметь мкакры/расширяемый синтаксис. Делаешь себе нужные операторы, а то и фрэймворк и в ус не дуешь. Я вот для внутреннего DSL описывающего тесты генераторы. Сейчас вот думаю, иметь бы такую штуку для генерации классов! А ты говоришь unless.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mystic Artifact, Вы писали:
MA> Совершенно нет. unless — не нужен ни в одном языке программирования, как раз потому, что он выражается через if.
А foreach выражается через for. Ну, а for выражается через while. А while, в свою очередь, выражается через концевую рекурсию и if!
Вывод! Выбрасываем на фиг из языка все циклы и оставляем только оптимизацию концевой рекурсии! Ну, как тебе вывод в соответствии с твоей минималистической логикой?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А вот foreach немерловый на фононе убожества из C# просто мега-крут!
Согласен, выглядит аппетитно, но для рядовых кодеров вроде меня, слишком дорого.
Т.к. 4 дотнет быстро сейчас приходит в упадок, под моно немерл уже не работает ни в каком виде.
А под корку нет редактора с автодополнением и подсветкой, версия при этом непонятно какая, если взять тот же foreach
В работе программиста конечно очень много психологии, если отбросить эмоции, то можно писать спокойно и на C#,
ну разве что МП будет на уровне предварительной кодогенерации. Жаль что SG работает только с partial class.
В целом такой подход довольно хорош.