@@ -210,6 +210,200 @@ namespace pythonic
210210 TypeTag tag_; // Type discriminator
211211
212212 public:
213+ // ============ Container Methods (Pythonic/C++ idioms) ============
214+
215+ // front() - return first element (list, ordered_set, ordered_dict, string)
216+ var front () const
217+ {
218+ switch (tag_)
219+ {
220+ case TypeTag::LIST :
221+ {
222+ const auto &lst = var_get<List>();
223+ if (lst.empty ())
224+ throw pythonic::PythonicIndexError (" list is empty" );
225+ return lst.front ();
226+ }
227+ case TypeTag::ORDEREDSET :
228+ {
229+ const auto &os = var_get<OrderedSet>();
230+ if (os.empty ())
231+ throw pythonic::PythonicIndexError (" ordered_set is empty" );
232+ return *os.begin ();
233+ }
234+ case TypeTag::ORDEREDDICT :
235+ {
236+ const auto &od = var_get<OrderedDict>();
237+ if (od.empty ())
238+ throw pythonic::PythonicIndexError (" ordereddict is empty" );
239+ return var (od.begin ()->first );
240+ }
241+ case TypeTag::STRING :
242+ {
243+ const auto &s = var_get<std::string>();
244+ if (s.empty ())
245+ throw pythonic::PythonicIndexError (" string is empty" );
246+ return var (std::string (1 , s.front ()));
247+ }
248+ default :
249+ throw pythonic::PythonicAttributeError (" front() not supported for this type" );
250+ }
251+ }
252+
253+ // back() - return last element (list, ordered_set, ordered_dict, string)
254+ var back () const
255+ {
256+ switch (tag_)
257+ {
258+ case TypeTag::LIST :
259+ {
260+ const auto &lst = var_get<List>();
261+ if (lst.empty ())
262+ throw pythonic::PythonicIndexError (" list is empty" );
263+ return lst.back ();
264+ }
265+ case TypeTag::ORDEREDSET :
266+ {
267+ const auto &os = var_get<OrderedSet>();
268+ if (os.empty ())
269+ throw pythonic::PythonicIndexError (" ordered_set is empty" );
270+ return *os.rbegin ();
271+ }
272+ case TypeTag::ORDEREDDICT :
273+ {
274+ const auto &od = var_get<OrderedDict>();
275+ if (od.empty ())
276+ throw pythonic::PythonicIndexError (" ordereddict is empty" );
277+ auto it = od.end ();
278+ --it;
279+ return var (it->first );
280+ }
281+ case TypeTag::STRING :
282+ {
283+ const auto &s = var_get<std::string>();
284+ if (s.empty ())
285+ throw pythonic::PythonicIndexError (" string is empty" );
286+ return var (std::string (1 , s.back ()));
287+ }
288+ default :
289+ throw pythonic::PythonicAttributeError (" back() not supported for this type" );
290+ }
291+ }
292+
293+ // at(index) - safe element access (list, string)
294+ var at (size_t index) const
295+ {
296+ switch (tag_)
297+ {
298+ case TypeTag::LIST :
299+ {
300+ const auto &lst = var_get<List>();
301+ if (index >= lst.size ())
302+ throw pythonic::PythonicIndexError (" list" , index, lst.size ());
303+ return lst[index];
304+ }
305+ case TypeTag::STRING :
306+ {
307+ const auto &s = var_get<std::string>();
308+ if (index >= s.size ())
309+ throw pythonic::PythonicIndexError (" string" , index, s.size ());
310+ return var (std::string (1 , s[index]));
311+ }
312+ default :
313+ throw pythonic::PythonicAttributeError (" at() not supported for this type" );
314+ }
315+ }
316+
317+ // empty() - check if container is empty (list, set, dict, ordered_set, ordered_dict, string)
318+ bool empty () const noexcept
319+ {
320+ switch (tag_)
321+ {
322+ case TypeTag::LIST :
323+ return var_get<List>().empty ();
324+ case TypeTag::SET :
325+ return var_get<Set>().empty ();
326+ case TypeTag::DICT :
327+ return var_get<Dict>().empty ();
328+ case TypeTag::ORDEREDSET :
329+ return var_get<OrderedSet>().empty ();
330+ case TypeTag::ORDEREDDICT :
331+ return var_get<OrderedDict>().empty ();
332+ case TypeTag::STRING :
333+ return var_get<std::string>().empty ();
334+ default :
335+ return true ;
336+ }
337+ }
338+
339+ // clear() - clear container (list, set, dict, ordered_set, ordered_dict, string)
340+ void clear ()
341+ {
342+ switch (tag_)
343+ {
344+ case TypeTag::LIST :
345+ var_get<List>().clear ();
346+ break ;
347+ case TypeTag::SET :
348+ var_get<Set>().clear ();
349+ break ;
350+ case TypeTag::DICT :
351+ var_get<Dict>().clear ();
352+ break ;
353+ case TypeTag::ORDEREDSET :
354+ var_get<OrderedSet>().clear ();
355+ break ;
356+ case TypeTag::ORDEREDDICT :
357+ var_get<OrderedDict>().clear ();
358+ break ;
359+ case TypeTag::STRING :
360+ var_get<std::string>().clear ();
361+ break ;
362+ default :
363+ throw pythonic::PythonicAttributeError (" clear() not supported for this type" );
364+ }
365+ }
366+
367+ // pop() - remove and return last element (list, ordered_set, ordered_dict)
368+ var pop ()
369+ {
370+ switch (tag_)
371+ {
372+ case TypeTag::LIST :
373+ {
374+ auto &lst = var_get<List>();
375+ if (lst.empty ())
376+ throw pythonic::PythonicIndexError (" pop from empty list" );
377+ var v = lst.back ();
378+ lst.pop_back ();
379+ return v;
380+ }
381+ case TypeTag::ORDEREDSET :
382+ {
383+ auto &os = var_get<OrderedSet>();
384+ if (os.empty ())
385+ throw pythonic::PythonicIndexError (" pop from empty ordered_set" );
386+ auto it = os.end ();
387+ --it;
388+ var v = *it;
389+ os.erase (it);
390+ return v;
391+ }
392+ case TypeTag::ORDEREDDICT :
393+ {
394+ auto &od = var_get<OrderedDict>();
395+ if (od.empty ())
396+ throw pythonic::PythonicIndexError (" pop from empty ordereddict" );
397+ auto it = od.end ();
398+ --it;
399+ var v = var (it->first );
400+ od.erase (it);
401+ return v;
402+ }
403+ default :
404+ throw pythonic::PythonicAttributeError (" pop() not supported for this type" );
405+ }
406+ }
213407 // ============ Internal Accessors for Union ============
214408 // These provide type-safe access to the union data
215409 // Template specializations handle each type
@@ -6856,7 +7050,7 @@ namespace pythonic
68567050 }
68577051 }
68587052
6859- // min() - minimum of list or two values
7053+ // min() - minimum of list or two values
68607054 inline var min (const var &a, const var &b)
68617055 {
68627056 if (a < b)
@@ -6980,77 +7174,6 @@ namespace pythonic
69807174 return var (false );
69817175 }
69827176
6983- // map() - apply function to each element, return new list
6984- template <typename Func>
6985- inline var map (Func func, const var &lst)
6986- {
6987- if (lst.type () != " list" )
6988- {
6989- throw pythonic::PythonicTypeError (" map() expects a list" );
6990- }
6991- List result;
6992- const auto &l = lst.get <List>();
6993- for (const auto &item : l)
6994- {
6995- result.push_back (func (item));
6996- }
6997- return var (result);
6998- }
6999-
7000- // filter() - filter elements by predicate, return new list
7001- template <typename Func>
7002- inline var filter (Func predicate, const var &lst)
7003- {
7004- if (lst.type () != " list" )
7005- {
7006- throw pythonic::PythonicTypeError (" filter() expects a list" );
7007- }
7008- List result;
7009- const auto &l = lst.get <List>();
7010- for (const auto &item : l)
7011- {
7012- if (predicate (item))
7013- {
7014- result.push_back (item);
7015- }
7016- }
7017- return var (result);
7018- }
7019-
7020- // reduce() - reduce list with binary function
7021- template <typename Func>
7022- inline var reduce (Func func, const var &lst, const var &initial)
7023- {
7024- if (lst.type () != " list" )
7025- {
7026- throw pythonic::PythonicTypeError (" reduce() expects a list" );
7027- }
7028- var result = initial;
7029- const auto &l = lst.get <List>();
7030- for (const auto &item : l)
7031- {
7032- result = func (result, item);
7033- }
7034- return result;
7035- }
7036-
7037- template <typename Func>
7038- inline var reduce (Func func, const var &lst)
7039- {
7040- if (lst.type () != " list" )
7041- {
7042- throw pythonic::PythonicTypeError (" reduce() expects a list" );
7043- }
7044- const auto &l = lst.get <List>();
7045- if (l.empty ())
7046- throw pythonic::PythonicValueError (" reduce() of empty sequence with no initial value" );
7047- var result = l[0 ];
7048- for (size_t i = 1 ; i < l.size (); ++i)
7049- {
7050- result = func (result, l[i]);
7051- }
7052- return result;
7053- }
70547177
70557178 // Python-like input() function
70567179
0 commit comments